Blob Blame Raw
From 0ab60ea381f3aeea5426e4a6aed5db7453216045 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
Date: Sat, 31 Aug 2019 13:01:49 +0200
Subject: [PATCH] Factor out click functionality from assert_and_click

There are two cases where the fixed combination of assert_screen with
the click functionality is problematic:

1. Multiple needles, where only some need/support clicking. This is
  typically solved with a combination of assert_screen + match_has_tag +
  assert_and_click. This is wasteful, as it checks twice for the same
  needle.

2. Repeated assert_and_click due to lost events. As it is impossible to
  know if an event was lost or just handled late, the repeated
  assert_and_click may encounter the just changed screen contents.

Splitting the click allows to do it conditionally, i.e. for (1.), just
replacing the assert_and_click by click_lastmatch, and for (2.), by using
something like:
```
assert_and_click(needle);
while(1) {
  assert_screen([needle, after]);
  last if match_has_tag(after);
  click_lastmatch;
}
```
For a sequence of clicks, the "after" can specify the coordinates for
the next click.
---
 OpenQA/Isotovideo/Interface.pm |  2 +-
 testapi.pm                     | 33 +++++++++++++++++++++++++++++----
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/OpenQA/Isotovideo/Interface.pm b/OpenQA/Isotovideo/Interface.pm
index 2bed4988..8ec5e37c 100644
--- a/OpenQA/Isotovideo/Interface.pm
+++ b/OpenQA/Isotovideo/Interface.pm
@@ -22,7 +22,7 @@ use warnings;
 # -> increment on every change of such APIs
 # -> never move that variable to another place (when refactoring)
 #    because it may be accessed by the tests itself
-our $version = 16;
+our $version = 17;
 
 # major version of the (web socket) API relevant to the developer mode
 # -> increment when making non-backward compatible changes to that API
diff --git a/testapi.pm b/testapi.pm
index b6b60e98..a7c0da5b 100755
--- a/testapi.pm
+++ b/testapi.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw($realname $username $password $serialdev %cmd %vars
 
   assert_screen check_screen assert_and_dclick save_screenshot
   assert_and_click mouse_hide mouse_set mouse_click
-  mouse_dclick mouse_tclick match_has_tag
+  mouse_dclick mouse_tclick match_has_tag click_lastmatch
 
   assert_script_run script_run assert_script_sudo script_sudo
   script_output validate_script_output
@@ -482,14 +482,39 @@ Throws C<FailedNeedle> exception if C<$timeout> timeout is hit. Default timeout
 
 sub assert_and_click {
     my ($mustmatch, %args) = @_;
-    $args{timeout}   //= $bmwqemu::default_timeout;
+    $args{timeout} //= $bmwqemu::default_timeout;
+
+    $last_matched_needle = assert_screen($mustmatch, $args{timeout});
+    bmwqemu::log_call(mustmatch => $mustmatch, %args);
+
+    my %click_args = map { $_ => $args{$_} } qw(button dclick mousehide);
+    return click_lastmatch(%click_args);
+}
+
+=head2 click_lastmatch
+
+  click_lastmatch([, button => $button] [, clicktime => $clicktime ] [, dclick => 1 ] [, mousehide => 1 ]);
+
+Click C<$button> at the "click_point" position as defined in the needle JSON file
+of the last matched needle, or - if the JSON has not explicit "click_point" -
+in the middle of the last match area. If C<$dclick> is set, do double click
+instead. Supported values for C<$button> are C<'left'> and C<'right'>, C<'left'>
+is the default. If C<$mousehide> is true then always move mouse to the 'hidden'
+position after clicking to prevent to disturb the area where user wants to
+assert/click in second step, otherwise move the mouse back to its previous
+position.
+
+=cut
+
+sub click_lastmatch {
+    my %args = @_;
     $args{button}    //= 'left';
     $args{dclick}    //= 0;
     $args{mousehide} //= 0;
 
-    $last_matched_needle = assert_screen($mustmatch, $args{timeout});
+    return unless $last_matched_needle;
+
     my $old_mouse_coords = query_isotovideo('backend_get_last_mouse_set');
-    bmwqemu::log_call(mustmatch => $mustmatch, %args);
 
     # determine click coordinates from the last area which has those explicitly specified
     my $relevant_area;
-- 
2.23.0