eyes_selenium 2.15.0 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.travis.yml +16 -0
  4. data/Gemfile +1 -1
  5. data/README.md +14 -4
  6. data/Rakefile +8 -1
  7. data/eyes_selenium.gemspec +26 -17
  8. data/lib/applitools/base/batch_info.rb +19 -0
  9. data/lib/applitools/base/dimension.rb +21 -0
  10. data/lib/applitools/base/environment.rb +19 -0
  11. data/lib/applitools/base/mouse_trigger.rb +33 -0
  12. data/lib/applitools/base/point.rb +21 -0
  13. data/lib/applitools/base/region.rb +77 -0
  14. data/lib/applitools/base/server_connector.rb +113 -0
  15. data/lib/applitools/base/session.rb +15 -0
  16. data/lib/applitools/base/start_info.rb +34 -0
  17. data/lib/applitools/base/test_results.rb +36 -0
  18. data/lib/applitools/base/text_trigger.rb +22 -0
  19. data/lib/applitools/eyes.rb +393 -0
  20. data/lib/applitools/eyes_logger.rb +40 -0
  21. data/lib/applitools/method_tracer.rb +22 -0
  22. data/lib/applitools/selenium/driver.rb +194 -0
  23. data/lib/applitools/selenium/element.rb +66 -0
  24. data/lib/applitools/selenium/keyboard.rb +27 -0
  25. data/lib/applitools/selenium/match_window_data.rb +24 -0
  26. data/lib/applitools/selenium/match_window_task.rb +190 -0
  27. data/lib/applitools/selenium/mouse.rb +62 -0
  28. data/lib/applitools/selenium/viewport_size.rb +128 -0
  29. data/lib/applitools/utils/image_delta_compressor.rb +150 -0
  30. data/lib/applitools/utils/image_utils.rb +63 -0
  31. data/lib/applitools/utils/utils.rb +52 -0
  32. data/lib/applitools/version.rb +3 -0
  33. data/lib/eyes_selenium.rb +9 -29
  34. data/spec/driver_passthrough_spec.rb +25 -25
  35. data/spec/spec_helper.rb +5 -8
  36. data/test/appium_example_script.rb +57 -0
  37. data/{test_script.rb → test/test_script.rb} +7 -9
  38. data/{watir_test.rb → test/watir_test_script.rb} +6 -4
  39. metadata +120 -48
  40. data/appium_eyes_example.rb +0 -56
  41. data/lib/eyes_selenium/capybara.rb +0 -21
  42. data/lib/eyes_selenium/eyes/agent_connector.rb +0 -76
  43. data/lib/eyes_selenium/eyes/batch_info.rb +0 -19
  44. data/lib/eyes_selenium/eyes/dimension.rb +0 -15
  45. data/lib/eyes_selenium/eyes/driver.rb +0 -266
  46. data/lib/eyes_selenium/eyes/element.rb +0 -78
  47. data/lib/eyes_selenium/eyes/environment.rb +0 -15
  48. data/lib/eyes_selenium/eyes/eyes.rb +0 -396
  49. data/lib/eyes_selenium/eyes/eyes_keyboard.rb +0 -25
  50. data/lib/eyes_selenium/eyes/eyes_mouse.rb +0 -60
  51. data/lib/eyes_selenium/eyes/failure_reports.rb +0 -4
  52. data/lib/eyes_selenium/eyes/match_level.rb +0 -8
  53. data/lib/eyes_selenium/eyes/match_window_data.rb +0 -18
  54. data/lib/eyes_selenium/eyes/match_window_task.rb +0 -182
  55. data/lib/eyes_selenium/eyes/mouse_trigger.rb +0 -23
  56. data/lib/eyes_selenium/eyes/region.rb +0 -72
  57. data/lib/eyes_selenium/eyes/screenshot_taker.rb +0 -18
  58. data/lib/eyes_selenium/eyes/session.rb +0 -14
  59. data/lib/eyes_selenium/eyes/start_info.rb +0 -32
  60. data/lib/eyes_selenium/eyes/test_results.rb +0 -32
  61. data/lib/eyes_selenium/eyes/text_trigger.rb +0 -19
  62. data/lib/eyes_selenium/eyes/viewport_size.rb +0 -105
  63. data/lib/eyes_selenium/eyes_logger.rb +0 -47
  64. data/lib/eyes_selenium/utils.rb +0 -6
  65. data/lib/eyes_selenium/utils/image_delta_compressor.rb +0 -149
  66. data/lib/eyes_selenium/utils/image_utils.rb +0 -76
  67. data/lib/eyes_selenium/version.rb +0 -3
@@ -0,0 +1,15 @@
1
+ module Applitools::Base
2
+ class Session
3
+ attr_reader :id, :url
4
+
5
+ def initialize(session_id, session_url, new_session)
6
+ @id = session_id
7
+ @url = session_url
8
+ @new_session = new_session
9
+ end
10
+
11
+ def new_session?
12
+ @new_session
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ module Applitools::Base
2
+ class StartInfo
3
+ attr_accessor :app_id_or_name, :scenario_id_or_name
4
+
5
+ def initialize(agent_id, app_id_or_name, scenario_id_or_name, batch_info, env_name, environment, match_level,
6
+ ver_id = nil, branch_name = nil, parent_branch_name = nil)
7
+ @agent_id = agent_id
8
+ @app_id_or_name = app_id_or_name
9
+ @ver_id = ver_id
10
+ @scenario_id_or_name = scenario_id_or_name
11
+ @batch_info = batch_info
12
+ @env_name = env_name
13
+ @environment = environment
14
+ @match_level = match_level
15
+ @branch_name = branch_name
16
+ @parent_branch_name = parent_branch_name
17
+ end
18
+
19
+ def to_hash
20
+ {
21
+ agent_id: @agent_id,
22
+ app_id_or_name: @app_id_or_name,
23
+ ver_id: @ver_id,
24
+ scenario_id_or_name: @scenario_id_or_name,
25
+ batch_info: @batch_info.to_hash,
26
+ env_name: @env_name,
27
+ environment: @environment.to_hash,
28
+ match_level: @match_level,
29
+ branch_name: @branch_name,
30
+ parent_branch_name: @parent_branch_name
31
+ }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ module Applitools::Base
2
+ class TestResults
3
+ attr_accessor :is_new, :url
4
+ attr_reader :steps, :matches, :mismatches, :missing, :exact_matches, :strict_matches, :content_matches,
5
+ :layout_matches, :none_matches, :is_passed
6
+
7
+ def initialize(steps = 0, matches = 0, mismatches = 0, missing = 0, exact_matches = 0, strict_matches = 0,
8
+ content_matches = 0, layout_matches = 0, none_matches = 0)
9
+ @steps = steps
10
+ @matches = matches
11
+ @mismatches = mismatches
12
+ @missing = missing
13
+ @exact_matches = exact_matches
14
+ @strict_matches = strict_matches
15
+ @content_matches = content_matches
16
+ @layout_matches = layout_matches
17
+ @none_matches = none_matches
18
+ @is_new = nil
19
+ @url = nil
20
+ end
21
+
22
+ def is_passed
23
+ !is_new && mismatches == 0 && missing == 0
24
+ end
25
+
26
+ def to_s
27
+ is_new_str = ''
28
+ unless is_new.nil?
29
+ is_new_str = is_new ? 'New test' : 'Existing test'
30
+ end
31
+
32
+ "#{is_new_str} [ steps: #{steps}, matches: #{matches}, mismatches: #{mismatches}, missing: #{missing} ], "\
33
+ "URL: #{url}"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ module Applitools::Base
2
+ class TextTrigger
3
+ attr_reader :text, :control
4
+
5
+ def initialize(text, control)
6
+ @text = text
7
+ @control = control
8
+ end
9
+
10
+ def to_hash
11
+ {
12
+ trigget_type: 'Text',
13
+ text: text,
14
+ control: control.to_hash
15
+ }
16
+ end
17
+
18
+ def to_s
19
+ "Text [#{@control}] #{@text}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,393 @@
1
+ require_relative 'version'
2
+ require_relative 'eyes_logger'
3
+
4
+ require 'forwardable'
5
+
6
+ class Applitools::Eyes
7
+ extend Forwardable
8
+
9
+ FAILURE_REPORTS = {
10
+ immediate: 'Immediate',
11
+ on_close: 'OnClose'
12
+ }.freeze
13
+
14
+ MATCH_LEVEL = {
15
+ none: 'None',
16
+ layout: 'Layout',
17
+ layout2: 'Layout2',
18
+ content: 'Content',
19
+ strict: 'Strict',
20
+ exact: 'Exact'
21
+ }.freeze
22
+
23
+ DEFAULT_MATCH_TIMEOUT = 2.0.freeze # Seconds
24
+ BASE_AGENT_ID = ('eyes.selenium.ruby/' + Applitools::VERSION).freeze
25
+
26
+ #
27
+ # Attributes:
28
+ #
29
+ # +app_name+:: +String+ The application name which was provided as an argument to +open+.
30
+ # +test_name+:: +String+ The test name which was provided as an argument to +open+.
31
+ # +is_open+:: +boolean+ Is there an open session.
32
+ # +viewport_size+:: +Hash+ The viewport size which was provided as an argument to +open+. Should include +width+
33
+ # and +height+.
34
+ # +driver+:: +Applitools::Selenium::Driver+ The driver instance wrapping the driver which was provided as an argument to +open+.
35
+ # +api_key+:: +String+ The user's API key.
36
+ # +match_timeout+:: +Float+ The default timeout for check_XXXX operations. (Seconds)
37
+ # +batch+:: +BatchInfo+ The current tests grouping, if any.
38
+ # +host_os+:: +String+ A string identifying the OS running the AUT. Set this if you wish to override Eyes' automatic
39
+ # inference.
40
+ # +host_app+:: +String+ A string identifying the container application running the AUT (e.g., Firefox). Set this if
41
+ # you wish to override Eyes' automatic inference.
42
+ # +branch_name+:: +String+ If set, names the branch in which the test should run.
43
+ # +parent_branch_name+:: +String+ If set, names the parent branch of the branch in which the test should run.
44
+ # +user_inputs+:: +Applitools::Base::MouseTrigger+/+Applitools::Selenium::KeyboardTrigger+ Mouse/Keyboard events which happened after
45
+ # the last visual validation.
46
+ # +save_new_tests+:: +boolean+ Whether or not new tests should be automatically accepted as baseline.
47
+ # +save_failed_tests+:: +boolean+ Whether or not failed tests should be automatically accepted as baseline.
48
+ # +match_level+:: +String+ The default match level for the entire session. See +Applitools::Eyes::MATCH_LEVEL+.
49
+ # +baseline_name+:: +String+ A string identifying the baseline which the test will be compared against. Set this if
50
+ # you wish to override Eyes' automatic baseline inference.
51
+ # +is_disabled+:: +boolean+ Set to +true+ if you wish to disable Eyes without deleting code (Eyes' methods act as a
52
+ # mock, and will do nothing).
53
+ # +server_url+:: +String+ The Eyes' server. Set this if you wish to override the default Eyes server URL.
54
+ # +agent_id+:: +String+ An optional string identifying the current library using the SDK.
55
+ # +log_handler+:: +Logger+ The logger to which Eyes will send info/debug messages.
56
+ # +failure_reports+:: +String+ Whether the current test will report mismatches immediately or when it is finished.
57
+ # See +Applitools::Eyes::FAILURE_REPORTS+.
58
+ # +rotation+:: +Integer+|+nil+ The degrees by which to rotate the screenshots received from the driver. Set this to
59
+ # override Eyes' automatic rotation inference. Positive values = clockwise rotation, negative
60
+ # values = counter-clockwise, 0 = force no rotation, +nil+ = use Eyes' automatic rotation inference.
61
+ attr_reader :app_name, :test_name, :is_open, :viewport_size, :driver
62
+ attr_accessor :match_timeout, :batch, :host_os, :host_app, :branch_name, :parent_branch_name, :user_inputs,
63
+ :save_new_tests, :save_failed_tests, :is_disabled, :server_url, :agent_id, :failure_reports, :match_level,
64
+ :baseline_name, :rotation
65
+
66
+ def_delegators 'Applitools::EyesLogger', :log_handler, :log_handler=
67
+ def_delegators 'Applitools::Base::ServerConnector', :api_key, :api_key=, :server_url, :server_url=
68
+
69
+ def full_agent_id
70
+ @full_agent_id ||= agent_id.nil? ? BASE_AGENT_ID : "#{agent_id} [#{BASE_AGENT_ID}]"
71
+ end
72
+
73
+ def title
74
+ unless @dont_get_title
75
+ begin
76
+ return driver.title
77
+ rescue
78
+ @dont_get_title = true
79
+ end
80
+ end
81
+
82
+ ''
83
+ end
84
+
85
+ def initialize(options = {})
86
+ @is_disabled = false
87
+
88
+ return if disabled?
89
+
90
+ @api_key = nil
91
+ @user_inputs = []
92
+
93
+ Applitools::Base::ServerConnector.server_url = options[:server_url]
94
+
95
+ @match_timeout = DEFAULT_MATCH_TIMEOUT
96
+ @match_level = Applitools::Eyes::MATCH_LEVEL[:exact]
97
+ @failure_reports = Applitools::Eyes::FAILURE_REPORTS[:on_close]
98
+ @save_new_tests = true
99
+ @save_failed_tests = false
100
+ @dont_get_title = false
101
+ end
102
+
103
+ def open(options = {})
104
+ @driver = get_driver(options)
105
+ return driver if disabled?
106
+
107
+ if api_key.nil?
108
+ raise Applitools::EyesError.new("API key not set! Log in to https://applitools.com to obtain your API Key and "\
109
+ "use 'api_key' to set it.")
110
+ end
111
+
112
+ if driver.is_a?(Selenium::WebDriver::Driver)
113
+ @driver = Applitools::Selenium::Driver.new(self, driver: driver)
114
+ elsif defined?(Appium::Driver) && driver.is_a?(Appium::Driver)
115
+ @driver = Applitools::Selenium::Driver.new(self, driver: driver.driver, is_mobile_device: true)
116
+ elsif defined?(Watir::Browser) && driver.is_a?(Watir::Browser)
117
+ @driver = Applitools::Selenium::Driver.new(self, driver: driver.driver)
118
+ else
119
+ unless driver.is_a?(Applitools::Selenium::Driver)
120
+ raise Applitools::EyesError.new("Driver is not a Selenium::WebDriver::Driver (#{driver.class.name})!")
121
+ end
122
+ end
123
+
124
+ if open?
125
+ abort_if_not_closed
126
+ msg = 'a test is already running'
127
+ Applitools::EyesLogger.warn(msg)
128
+
129
+ raise Applitools::EyesError.new(msg)
130
+ end
131
+
132
+ @user_inputs = []
133
+ @app_name = options.fetch(:app_name)
134
+ @test_name = options.fetch(:test_name)
135
+ @viewport_size = options.fetch(:viewport_size, nil)
136
+
137
+ @is_open = true
138
+
139
+ driver
140
+ end
141
+
142
+ def open?
143
+ is_open
144
+ end
145
+
146
+ def clear_user_inputs
147
+ user_inputs.clear
148
+ end
149
+
150
+ def check_region(how, what, tag = nil, specific_timeout = -1)
151
+ Applitools::EyesLogger.debug 'check_region called'
152
+ return if disabled?
153
+
154
+ # We have to start the session if it's not started, since we want the viewport size to be set before getting the
155
+ # element's position and size
156
+ raise Applitools::EyesError.new('Eyes not open') unless open?
157
+
158
+ unless @session
159
+ Applitools::EyesLogger.debug 'Starting session...'
160
+ start_session
161
+ Applitools::EyesLogger.debug 'Done! Creating match window task...'
162
+ @match_window_task = Applitools::Selenium::MatchWindowTask.new(self, @session, driver, match_timeout)
163
+ Applitools::EyesLogger.debug 'Done!'
164
+ end
165
+
166
+ Applitools::EyesLogger.debug 'Finding element...'
167
+ element_to_check = driver.find_element(how, what)
168
+ Applitools::EyesLogger.debug 'Done! Getting element location...'
169
+ location = element_to_check.location
170
+ Applitools::EyesLogger.debug 'Done! Getting element size...'
171
+ size = element_to_check.size
172
+ Applitools::EyesLogger.debug 'Done! Creating region...'
173
+ region = Applitools::Base::Region.new(location.x, location.y, size.width, size.height)
174
+ Applitools::EyesLogger.debug 'Done! Checking region...'
175
+ check_region_(region, tag, specific_timeout)
176
+ Applitools::EyesLogger.debug 'Done!'
177
+ end
178
+
179
+ def check_window(tag = nil, specific_timeout = -1)
180
+ check_region_(Applitools::Base::Region::EMPTY, tag, specific_timeout)
181
+ end
182
+
183
+ def close(raise_ex=true)
184
+ return if disabled?
185
+ @is_open = false
186
+
187
+ # If there's no running session, the test was never started (never reached check_window).
188
+ unless @session
189
+ Applitools::EyesLogger.debug 'Server session was not started'
190
+ Applitools::EyesLogger.info '--- Empty test ended.'
191
+
192
+ return Applitools::Base::TestResults.new
193
+ end
194
+
195
+ session_results_url = @session.url
196
+ new_session = @session.new_session?
197
+ Applitools::EyesLogger.debug 'Ending server session...'
198
+ save = (new_session && save_new_tests) || (!new_session && save_failed_tests)
199
+ results = Applitools::Base::ServerConnector.stop_session(@session, false, save)
200
+ results.is_new = new_session
201
+ results.url = session_results_url
202
+ Applitools::EyesLogger.debug "Results: #{results}"
203
+
204
+ @session = nil
205
+
206
+ if new_session
207
+ instructions = "Please approve the new baseline at #{session_results_url}"
208
+ Applitools::EyesLogger.info "--- New test ended. #{instructions}"
209
+
210
+ if raise_ex
211
+ message = "'#{@session_start_info.scenario_id_or_name}' of '#{@session_start_info.app_id_or_name}'. "\
212
+ "#{instructions}"
213
+
214
+ raise Applitools::NewTestError.new(message, results)
215
+ end
216
+
217
+ return results
218
+ end
219
+
220
+ unless results.is_passed
221
+ # Test failed
222
+ Applitools::EyesLogger.info "--- Failed test ended. See details at #{session_results_url}"
223
+
224
+ if raise_ex
225
+ message = "'#{@session_start_info.scenario_id_or_name}' of '#{@session_start_info.app_id_or_name}'. see "\
226
+ "details at #{session_results_url}"
227
+
228
+ raise Applitools::TestFailedError.new(message, results)
229
+ end
230
+
231
+ return results
232
+ end
233
+
234
+ # Test passed
235
+ Applitools::EyesLogger.info "--- Test passed. See details at #{session_results_url}"
236
+
237
+ results
238
+ end
239
+
240
+ ## Use this method to perform seamless testing with selenium through eyes driver.
241
+ ## Using Selenium methods inside the 'test' block will send the messages to Selenium
242
+ ## after creating the Eyes triggers for them.
243
+ ##
244
+ ## Example:
245
+ # eyes.test(app_name: 'my app1', test_name: 'my test') do |d|
246
+ # get "http://www.google.com"
247
+ # check_window("initial")
248
+ # end
249
+ #noinspection RubyUnusedLocalVariable
250
+ def test(options = {}, &block)
251
+ begin
252
+ open(options)
253
+ yield(driver)
254
+ close
255
+ ensure
256
+ abort_if_not_closed
257
+ end
258
+ end
259
+
260
+ def abort_if_not_closed
261
+ return if disabled?
262
+
263
+ @is_open = false
264
+
265
+ return unless @session
266
+
267
+ begin
268
+ Applitools::Base::ServerConnector.stop_session(@session, true, false)
269
+ rescue Exception, Applitools::EyesError => e
270
+ Applitools::EyesLogger.error "Failed to abort server session: #{e.message}!"
271
+ ensure
272
+ @session = nil
273
+ end
274
+ end
275
+
276
+ private
277
+
278
+ def disabled?
279
+ is_disabled
280
+ end
281
+
282
+ def get_driver(options)
283
+ # TODO remove the "browser" related block when possible. It's for backward compatibility.
284
+ if options.has_key?(:browser)
285
+ Applitools::EyesLogger.warn('"browser" key is deprecated, please use "driver" instead.')
286
+
287
+ return options[:browser]
288
+ end
289
+
290
+ options.fetch(:driver, nil)
291
+ end
292
+
293
+ def inferred_environment
294
+ user_agent = driver.user_agent
295
+ "useragent:#{user_agent}" if user_agent
296
+ end
297
+
298
+ # Application environment is the environment (e.g., the host OS) which runs the application under test.
299
+ #
300
+ # Returns:
301
+ # +Applitools::Base::Environment+ The application environment.
302
+ def app_environment
303
+ os = host_os
304
+ if os.nil?
305
+ Applitools::EyesLogger.info 'No OS set, checking for mobile OS...'
306
+ if driver.mobile_device?
307
+ platform_name = nil
308
+ Applitools::EyesLogger.info 'Mobile device detected! Checking device type..'
309
+ if driver.android?
310
+ Applitools::EyesLogger.info 'Android detected.'
311
+ platform_name = 'Android'
312
+ elsif driver.ios?
313
+ Applitools::EyesLogger.info 'iOS detected.'
314
+ platform_name = 'iOS'
315
+ else
316
+ Applitools::EyesLogger.warn 'Unknown device type.'
317
+ end
318
+ # We only set the OS if we identified the device type.
319
+ unless platform_name.nil?
320
+ platform_version = driver.platform_version
321
+ if platform_version.nil?
322
+ os = platform_name
323
+ else
324
+ # Notice that Ruby's +split+ function's +limit+ is the number of elements, whereas in Python it is the
325
+ # maximum splits performed (which is why they are set differently).
326
+ major_version = platform_version.split('.', 2)[0]
327
+ os = "#{platform_name} #{major_version}"
328
+ end
329
+ Applitools::EyesLogger.info "Setting OS: #{os}"
330
+ end
331
+ else
332
+ Applitools::EyesLogger.info 'No mobile OS detected.'
333
+ end
334
+ end
335
+
336
+ # Create and return the environment object.
337
+ Applitools::Base::Environment.new(os, host_app, viewport_size, inferred_environment)
338
+ end
339
+
340
+ def start_session
341
+ assign_viewport_size
342
+ @batch ||= Applitools::Base::BatchInfo.new
343
+ app_env = app_environment
344
+
345
+ @session_start_info = Applitools::Base::StartInfo.new(full_agent_id, app_name, test_name, batch, baseline_name,
346
+ app_env, match_level, nil, branch_name, parent_branch_name)
347
+ @session = Applitools::Base::ServerConnector.start_session(@session_start_info)
348
+ @should_match_window_run_once_on_timeout = @session.new_session?
349
+ end
350
+
351
+ def viewport_size?
352
+ viewport_size
353
+ end
354
+
355
+ def assign_viewport_size
356
+ if viewport_size?
357
+ @viewport_size = Applitools::Selenium::ViewportSize.new(driver, viewport_size)
358
+ viewport_size.set
359
+ else
360
+ @viewport_size = Applitools::Selenium::ViewportSize.new(driver).extract_viewport_from_browser!
361
+ end
362
+ end
363
+
364
+ def check_region_(region, tag = nil, specific_timeout = -1)
365
+ return if disabled?
366
+ Applitools::EyesLogger.info "check_region_('#{tag}', #{specific_timeout})"
367
+ raise Applitools::EyesError.new('region cannot be nil!') if region.nil?
368
+ raise Applitools::EyesError.new('Eyes not open') unless open?
369
+
370
+ unless @session
371
+ Applitools::EyesLogger.debug 'Starting session...'
372
+ start_session
373
+ Applitools::EyesLogger.debug 'Done! Creating match window task...'
374
+ @match_window_task = Applitools::Selenium::MatchWindowTask.new(self, @session, driver, match_timeout)
375
+ Applitools::EyesLogger.debug 'Done!'
376
+ end
377
+
378
+ Applitools::EyesLogger.debug 'Starting match task...'
379
+ as_expected = @match_window_task.match_window(region, specific_timeout, tag, rotation,
380
+ @should_match_window_run_once_on_timeout)
381
+ Applitools::EyesLogger.debug 'Match window done!'
382
+ unless as_expected
383
+ @should_match_window_run_once_on_timeout = true
384
+ unless @session.new_session?
385
+ Applitools::EyesLogger.info %( mismatch #{ tag ? '' : "(#{tag})" } )
386
+ if failure_reports.to_i == Applitools::Eyes::FAILURE_REPORTS[:immediate]
387
+ raise Applitools::TestFailedError.new("Mismatch found in '#{@session_start_info.scenario_id_or_name}' "\
388
+ "of '#{@session_start_info.app_id_or_name}'")
389
+ end
390
+ end
391
+ end
392
+ end
393
+ end