eyes_selenium 2.8.0 → 2.9.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.
- checksums.yaml +4 -4
 - data/appium_eyes_example.rb +41 -31
 - data/eyes_selenium.gemspec +3 -2
 - data/lib/eyes_selenium/eyes/agent_connector.rb +0 -2
 - data/lib/eyes_selenium/eyes/driver.rb +89 -9
 - data/lib/eyes_selenium/eyes/eyes.rb +45 -15
 - data/lib/eyes_selenium/eyes/match_window_task.rb +2 -1
 - data/lib/eyes_selenium/eyes/viewport_size.rb +11 -3
 - data/lib/eyes_selenium/utils.rb +1 -0
 - data/lib/eyes_selenium/utils/image_delta_compressor.rb +5 -5
 - data/lib/eyes_selenium/utils/image_utils.rb +76 -0
 - data/lib/eyes_selenium/version.rb +1 -1
 - data/test_script.rb +2 -2
 - metadata +19 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9ebc04f208fa510c98a5260826fb118d86291185
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: d5226529324ab94f2cca6a96b059851b11102384
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 6038fb5f5d17c9eb8a9d80d984c4160ddbac031e81d442e50cb8223124d45199192b56bcf80dedd5573d2d94c8157424a123bd7f32140165e6eea7ec69be87d8
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: df5fba1575662b834bf311a14a5f21a97a69612204e8957867c86cdf10edd0c6b989216ffb229a60d8b7c5e99737517f6ec8f8d8e67664fe033fbf86779b96ad
         
     | 
    
        data/appium_eyes_example.rb
    CHANGED
    
    | 
         @@ -1,47 +1,57 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'eyes_selenium'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'openssl'
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            ## 
         
     | 
| 
      
 4 
     | 
    
         
            +
            OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
         
     | 
| 
      
 5 
     | 
    
         
            +
            ##
         
     | 
| 
       6 
6 
     | 
    
         
             
            # Based on Appium example: https://github.com/appium/appium/blob/master/sample-code/examples/ruby/
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
            desired_capabilities = {
         
     | 
| 
       9 
     | 
    
         
            -
                "device" => "Android",
         
     | 
| 
       10 
     | 
    
         
            -
                "version" => "4.2",
         
     | 
| 
       11 
     | 
    
         
            -
                "app" => "http://appium.s3.amazonaws.com/NotesList.apk",
         
     | 
| 
       12 
     | 
    
         
            -
                "app-package" => "com.example.android.notepad",
         
     | 
| 
       13 
     | 
    
         
            -
                "app-activity" => ".NotesList"
         
     | 
| 
       14 
     | 
    
         
            -
            }
         
     | 
| 
       15 
8 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
            def  
     | 
| 
       17 
     | 
    
         
            -
            	 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
            def android_caps
         
     | 
| 
      
 10 
     | 
    
         
            +
            	{
         
     | 
| 
      
 11 
     | 
    
         
            +
            			deviceName:          'Samsung Galaxy S4 Emulator',
         
     | 
| 
      
 12 
     | 
    
         
            +
            			platformName:        'Android',
         
     | 
| 
      
 13 
     | 
    
         
            +
            			platformVersion:     4.4,
         
     | 
| 
      
 14 
     | 
    
         
            +
            			app:                 '/Users/daniel/test/NotesList.apk',
         
     | 
| 
      
 15 
     | 
    
         
            +
            			appPackage:        	 'com.example.android.notepad',
         
     | 
| 
      
 16 
     | 
    
         
            +
            			appActivity:         '.NotesList',
         
     | 
| 
      
 17 
     | 
    
         
            +
            			# orientation:				 'landscape',
         
     | 
| 
      
 18 
     | 
    
         
            +
            			newCommandTimeout:	 300
         
     | 
| 
      
 19 
     | 
    
         
            +
            	}
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
            def ios_caps
         
     | 
| 
      
 22 
     | 
    
         
            +
            	{
         
     | 
| 
      
 23 
     | 
    
         
            +
            			deviceName:          'iPhone 6',
         
     | 
| 
      
 24 
     | 
    
         
            +
            			platformName:        'ios',
         
     | 
| 
      
 25 
     | 
    
         
            +
            			platformVersion:     8.3,
         
     | 
| 
      
 26 
     | 
    
         
            +
            			app:                 '/Users/daniel/Library/Developer/Xcode/DerivedData/HelloXcode-cldusyhxlaclfkbirmthhbgpchqv/Build/Products/Debug-iphonesimulator/HelloXcode.app',
         
     | 
| 
      
 27 
     | 
    
         
            +
            			orientation:	 'landscape',
         
     | 
| 
      
 28 
     | 
    
         
            +
            			newCommandTimeout:	 300
         
     | 
| 
      
 29 
     | 
    
         
            +
            	}
         
     | 
| 
       21 
30 
     | 
    
         
             
            end
         
     | 
| 
       22 
31 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
            def  
     | 
| 
       24 
     | 
    
         
            -
            	 
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
            	 
     | 
| 
      
 32 
     | 
    
         
            +
            def appium_opts
         
     | 
| 
      
 33 
     | 
    
         
            +
            	{
         
     | 
| 
      
 34 
     | 
    
         
            +
            			server_url: 'http://127.0.0.1:4723/wd/hub',
         
     | 
| 
      
 35 
     | 
    
         
            +
            	}
         
     | 
| 
       27 
36 
     | 
    
         
             
            end
         
     | 
| 
       28 
37 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            @eyes = Applitools::Eyes.new(server_url: 'https://localhost.applitools.com')
         
     | 
| 
      
 40 
     | 
    
         
            +
            @eyes.log_handler = Logger.new(STDOUT)
         
     | 
| 
      
 41 
     | 
    
         
            +
            @eyes.api_key = ENV['APPLITOOLS_API_KEY']
         
     | 
| 
       30 
42 
     | 
    
         
             
            begin
         
     | 
| 
       31 
     | 
    
         
            -
            	@driver =  
     | 
| 
       32 
     | 
    
         
            -
            	@driver =  
     | 
| 
      
 43 
     | 
    
         
            +
            	@driver = Appium::Driver.new({caps: android_caps, appium_lib: appium_opts})
         
     | 
| 
      
 44 
     | 
    
         
            +
            	# @driver = Appium::Driver.new({caps: ios_caps, appium_lib: appium_opts})
         
     | 
| 
      
 45 
     | 
    
         
            +
            	@driver.start_driver
         
     | 
| 
      
 46 
     | 
    
         
            +
            	# @driver.driver.rotate :landscape
         
     | 
| 
      
 47 
     | 
    
         
            +
              puts "Screen size: #{@driver.driver.manage.window.size}"
         
     | 
| 
      
 48 
     | 
    
         
            +
              puts "orientation: #{@driver.driver.orientation}"
         
     | 
| 
      
 49 
     | 
    
         
            +
              puts @driver.caps
         
     | 
| 
      
 50 
     | 
    
         
            +
            	@eyes.open(app_name: 'Selenium Israel', test_name: 'Appium Notepad', driver: @driver)
         
     | 
| 
       33 
51 
     | 
    
         
             
            	@eyes.check_window("No notes")
         
     | 
| 
       34 
52 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
            	create_note "I didn't expect a kind of Spanish Inquisition!"
         
     | 
| 
       36 
     | 
    
         
            -
            	create_note "Nobody expects the Spanish Inquisition!"
         
     | 
| 
       37 
     | 
    
         
            -
            	@eyes.check_window("Two notes")
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
            	clear_note_by_text "I didn't expect a kind of Spanish Inquisition!"
         
     | 
| 
       40 
     | 
    
         
            -
            	@eyes.check_window("One note")
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
53 
     | 
    
         
             
            	@eyes.close
         
     | 
| 
       43 
54 
     | 
    
         
             
            ensure
         
     | 
| 
       44 
     | 
    
         
            -
            	sleep 5
         
     | 
| 
       45 
55 
     | 
    
         
             
            	@eyes.abort_if_not_closed
         
     | 
| 
       46 
     | 
    
         
            -
            	@driver. 
     | 
| 
      
 56 
     | 
    
         
            +
            	@driver.driver_quit
         
     | 
| 
       47 
57 
     | 
    
         
             
            end
         
     | 
    
        data/eyes_selenium.gemspec
    CHANGED
    
    | 
         @@ -18,8 +18,9 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       18 
18 
     | 
    
         
             
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
       19 
19 
     | 
    
         
             
              spec.require_paths = ["lib"]
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
              spec.add_dependency "selenium-webdriver", [">= 2. 
     | 
| 
       22 
     | 
    
         
            -
              spec.add_dependency " 
     | 
| 
      
 21 
     | 
    
         
            +
              spec.add_dependency "selenium-webdriver", [">= 2.45.0"]
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.add_dependency "appium_lib", [">= 6.0.0"]
         
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_dependency "httparty"
         
     | 
| 
       23 
24 
     | 
    
         
             
              spec.add_dependency "oily_png", [">= 1.1.0"] 
         
     | 
| 
       24 
25 
     | 
    
         | 
| 
       25 
26 
     | 
    
         
             
              spec.add_development_dependency "bundler", "~> 1.3"
         
     | 
| 
         @@ -35,10 +35,8 @@ class Applitools::AgentConnector 
     | 
|
| 
       35 
35 
     | 
    
         
             
              def start_session(session_start_info)
         
     | 
| 
       36 
36 
     | 
    
         
             
               self.class.headers 'Content-Type' => 'application/json'
         
     | 
| 
       37 
37 
     | 
    
         
             
               res = self.class.post(@endpoint_uri, query: {apiKey: api_key}, body: { startInfo: session_start_info.to_hash }.to_json)
         
     | 
| 
       38 
     | 
    
         
            -
               EyesLogger.debug "Got response! #{res}"
         
     | 
| 
       39 
38 
     | 
    
         
             
               status_code = res.response.message
         
     | 
| 
       40 
39 
     | 
    
         
             
               parsed_res = res.parsed_response
         
     | 
| 
       41 
     | 
    
         
            -
               EyesLogger.debug "Parsed response #{parsed_res}"
         
     | 
| 
       42 
40 
     | 
    
         
             
               Applitools::Session.new(parsed_res['id'], parsed_res['url'], status_code == 'Created' )
         
     | 
| 
       43 
41 
     | 
    
         
             
              end
         
     | 
| 
       44 
42 
     | 
    
         | 
| 
         @@ -1,7 +1,35 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'socket'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'selenium-webdriver'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'appium_lib'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
            class  Applitools::Driver
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
              # Prepares an image for being sent to the Eyes server (e.g., handling rotation, scaling etc.).
         
     | 
| 
      
 8 
     | 
    
         
            +
              #
         
     | 
| 
      
 9 
     | 
    
         
            +
              # +driver+:: +Applitools::Driver+ The driver which produced the screenshot.
         
     | 
| 
      
 10 
     | 
    
         
            +
              # +image+:: +ChunkyPNG::Canvas+ The image to normalize.
         
     | 
| 
      
 11 
     | 
    
         
            +
              #
         
     | 
| 
      
 12 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 13 
     | 
    
         
            +
              # +Integer+ The rotation of the screenshot we get from the webdriver (degrees).
         
     | 
| 
      
 14 
     | 
    
         
            +
              def self.normalize_image!(driver, image, rotation=0)
         
     | 
| 
      
 15 
     | 
    
         
            +
                EyesLogger.debug "#{__method__}()"
         
     | 
| 
      
 16 
     | 
    
         
            +
                # Handling rotation
         
     | 
| 
      
 17 
     | 
    
         
            +
                num_quadrants = 0
         
     | 
| 
      
 18 
     | 
    
         
            +
                if rotation != 0
         
     | 
| 
      
 19 
     | 
    
         
            +
                  if rotation % 90 != 0
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise Applitools::EyesError.new "Currently only quadrant rotations are supported. Current rotation: #{rotation}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  num_quadrants = (rotation / 90).to_i
         
     | 
| 
      
 23 
     | 
    
         
            +
                elsif driver.mobile_device? && driver.landscape_orientation? && image.height > image.width
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # For Android, we need to rotate images to the right, and for iOS to the left.
         
     | 
| 
      
 25 
     | 
    
         
            +
                  num_quadrants = driver.android? ? 1 : -1
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
                if num_quadrants != 0
         
     | 
| 
      
 28 
     | 
    
         
            +
                  Applitools::Utils::ImageUtils.quadrant_rotate!(image, num_quadrants)
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
       5 
33 
     | 
    
         
             
              include Selenium::WebDriver::DriverExtensions::HasInputDevices
         
     | 
| 
       6 
34 
     | 
    
         | 
| 
       7 
35 
     | 
    
         
             
              attr_reader :remote_server_url, :remote_session_id, :screenshot_taker, :eyes
         
     | 
| 
         @@ -9,7 +37,7 @@ class  Applitools::Driver 
     | 
|
| 
       9 
37 
     | 
    
         | 
| 
       10 
38 
     | 
    
         
             
              DRIVER_METHODS = [
         
     | 
| 
       11 
39 
     | 
    
         
             
                :title, :execute_script, :execute_async_script, :quit, :close, :get,
         
     | 
| 
       12 
     | 
    
         
            -
                :post, :page_source, :window_handles, :window_handle, :switch_to, 
     | 
| 
      
 40 
     | 
    
         
            +
                :post, :page_source, :window_handles, :window_handle, :switch_to,
         
     | 
| 
       13 
41 
     | 
    
         
             
                :navigate, :manage, :capabilities
         
     | 
| 
       14 
42 
     | 
    
         
             
              ]
         
     | 
| 
       15 
43 
     | 
    
         | 
| 
         @@ -17,8 +45,9 @@ class  Applitools::Driver 
     | 
|
| 
       17 
45 
     | 
    
         
             
              #
         
     | 
| 
       18 
46 
     | 
    
         
             
              def initialize(eyes, options)
         
     | 
| 
       19 
47 
     | 
    
         
             
                @driver = options[:driver]
         
     | 
| 
      
 48 
     | 
    
         
            +
                @is_mobile_device = options.fetch(:is_mobile_device, false)
         
     | 
| 
       20 
49 
     | 
    
         
             
                @eyes = eyes
         
     | 
| 
       21 
     | 
    
         
            -
                # FIXME fix getting "remote address url" or remove "Screenshot taker"  
     | 
| 
      
 50 
     | 
    
         
            +
                # FIXME fix getting "remote address url" or remove "Screenshot taker" altogether.
         
     | 
| 
       22 
51 
     | 
    
         
             
                # @remote_server_url = address_of_remote_server
         
     | 
| 
       23 
52 
     | 
    
         
             
                @remote_server_url = 'MOCK_URL'
         
     | 
| 
       24 
53 
     | 
    
         
             
                @remote_session_id = remote_session_id
         
     | 
| 
         @@ -29,7 +58,7 @@ class  Applitools::Driver 
     | 
|
| 
       29 
58 
     | 
    
         
             
                  else
         
     | 
| 
       30 
59 
     | 
    
         
             
                    @screenshot_taker = Applitools::ScreenshotTaker.new(@remote_server_url, @remote_session_id)
         
     | 
| 
       31 
60 
     | 
    
         
             
                  end
         
     | 
| 
       32 
     | 
    
         
            -
                rescue => e 
     | 
| 
      
 61 
     | 
    
         
            +
                rescue => e
         
     | 
| 
       33 
62 
     | 
    
         
             
                  raise Applitools::EyesError.new "Can't take screenshots (#{e.message})"
         
     | 
| 
       34 
63 
     | 
    
         
             
                end
         
     | 
| 
       35 
64 
     | 
    
         
             
              end
         
     | 
| 
         @@ -40,14 +69,64 @@ class  Applitools::Driver 
     | 
|
| 
       40 
69 
     | 
    
         
             
                end
         
     | 
| 
       41 
70 
     | 
    
         
             
              end
         
     | 
| 
       42 
71 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
               
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 72 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 73 
     | 
    
         
            +
              # +String+ The platform name or +nil+ if it is undefined.
         
     | 
| 
      
 74 
     | 
    
         
            +
              def platform_name
         
     | 
| 
      
 75 
     | 
    
         
            +
                driver.capabilities['platformName']
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 79 
     | 
    
         
            +
              # +String+ The platform version or +nil+ if it is undefined.
         
     | 
| 
      
 80 
     | 
    
         
            +
              def platform_version
         
     | 
| 
      
 81 
     | 
    
         
            +
                version = driver.capabilities['platformVersion']
         
     | 
| 
      
 82 
     | 
    
         
            +
                version.nil? ? nil : version.to_s
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
       45 
84 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 85 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 86 
     | 
    
         
            +
              # +true+ if the driver is an Android driver.
         
     | 
| 
      
 87 
     | 
    
         
            +
              def android?
         
     | 
| 
      
 88 
     | 
    
         
            +
                platform_name.to_s.upcase == 'ANDROID'
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 92 
     | 
    
         
            +
              # +true+ if the driver is an iOS driver.
         
     | 
| 
      
 93 
     | 
    
         
            +
              def ios?
         
     | 
| 
      
 94 
     | 
    
         
            +
                platform_name.to_s.upcase == 'IOS'
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 98 
     | 
    
         
            +
              # +true+ if the driver orientation is landscape.
         
     | 
| 
      
 99 
     | 
    
         
            +
              def landscape_orientation?
         
     | 
| 
      
 100 
     | 
    
         
            +
                driver.orientation.to_s.upcase == 'LANDSCAPE'
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 104 
     | 
    
         
            +
              # +true+ if the platform running the test is a mobile platform. +false+ otherwise.
         
     | 
| 
      
 105 
     | 
    
         
            +
              def mobile_device?
         
     | 
| 
      
 106 
     | 
    
         
            +
                # We CAN'T check if the device is an +Appium::Driver+ since it is not a RemoteWebDriver. Because of that we use a
         
     | 
| 
      
 107 
     | 
    
         
            +
                # flag we got as an option in the constructor.
         
     | 
| 
      
 108 
     | 
    
         
            +
                @is_mobile_device
         
     | 
| 
      
 109 
     | 
    
         
            +
              end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
              def screenshot_as(output_type)
         
     | 
| 
      
 112 
     | 
    
         
            +
                # TODO Check if screenshot_taker is still required
         
     | 
| 
      
 113 
     | 
    
         
            +
                if screenshot_taker
         
     | 
| 
      
 114 
     | 
    
         
            +
                  if output_type.downcase.to_sym != :base64
         
     | 
| 
      
 115 
     | 
    
         
            +
                    raise Applitools::EyesError.new("#{output_type} output type not supported for screenshot")
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                  screenshot64 = screenshot_taker.screenshot
         
     | 
| 
      
 118 
     | 
    
         
            +
                else
         
     | 
| 
      
 119 
     | 
    
         
            +
                  screenshot = driver.screenshot_as(output_type)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  # We only support additional processing of the output (such as rotation) for Base64 type of screenshots.
         
     | 
| 
      
 121 
     | 
    
         
            +
                  if output_type.downcase.to_sym != :base64
         
     | 
| 
      
 122 
     | 
    
         
            +
                    return screenshot
         
     | 
| 
      
 123 
     | 
    
         
            +
                  end
         
     | 
| 
      
 124 
     | 
    
         
            +
                  screenshot64 = screenshot
         
     | 
| 
       48 
125 
     | 
    
         
             
                end
         
     | 
| 
       49 
     | 
    
         
            -
                 
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
      
 126 
     | 
    
         
            +
                screenshot = Applitools::Utils::ImageUtils.png_image_from_base64(screenshot64)
         
     | 
| 
      
 127 
     | 
    
         
            +
                Applitools::Driver.normalize_image!(self, screenshot)
         
     | 
| 
      
 128 
     | 
    
         
            +
                Applitools::Utils::ImageUtils.base64_from_png_image(screenshot)
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
       51 
130 
     | 
    
         | 
| 
       52 
131 
     | 
    
         
             
              def mouse
         
     | 
| 
       53 
132 
     | 
    
         
             
                Applitools::EyesMouse.new(self, driver.mouse)
         
     | 
| 
         @@ -103,6 +182,7 @@ class  Applitools::Driver 
     | 
|
| 
       103 
182 
     | 
    
         
             
                execute_script 'return navigator.userAgent'
         
     | 
| 
       104 
183 
     | 
    
         
             
              rescue => e
         
     | 
| 
       105 
184 
     | 
    
         
             
                EyesLogger.info "getUserAgent(): Failed to obtain user-agent string (#{e.message})"
         
     | 
| 
      
 185 
     | 
    
         
            +
                return nil
         
     | 
| 
       106 
186 
     | 
    
         
             
              end
         
     | 
| 
       107 
187 
     | 
    
         | 
| 
       108 
188 
     | 
    
         
             
              private
         
     | 
| 
         @@ -91,6 +91,8 @@ class Applitools::Eyes 
     | 
|
| 
       91 
91 
     | 
    
         | 
| 
       92 
92 
     | 
    
         
             
                if driver.is_a?(Selenium::WebDriver::Driver)
         
     | 
| 
       93 
93 
     | 
    
         
             
                  @driver = Applitools::Driver.new(self, {driver: driver})
         
     | 
| 
      
 94 
     | 
    
         
            +
                elsif driver.is_a?(Appium::Driver)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  @driver = Applitools::Driver.new(self, {driver: driver.driver, is_mobile_device: true})
         
     | 
| 
       94 
96 
     | 
    
         
             
                else
         
     | 
| 
       95 
97 
     | 
    
         
             
                  unless driver.is_a?(Applitools::Driver)
         
     | 
| 
       96 
98 
     | 
    
         
             
                    raise Applitools::EyesError.new("Driver is not a Selenium::WebDriver::Driver (#{driver.class.name})")
         
     | 
| 
         @@ -250,32 +252,60 @@ class Applitools::Eyes 
     | 
|
| 
       250 
252 
     | 
    
         
             
                  params.fetch(:driver, nil)
         
     | 
| 
       251 
253 
     | 
    
         
             
                end
         
     | 
| 
       252 
254 
     | 
    
         | 
| 
       253 
     | 
    
         
            -
                def mobile_os
         
     | 
| 
       254 
     | 
    
         
            -
                  caps = driver.capabilities
         
     | 
| 
       255 
     | 
    
         
            -
                  device = caps['device'] ? caps['device'] : caps[:platform]
         
     | 
| 
       256 
     | 
    
         
            -
                  if device && device!=''
         
     | 
| 
       257 
     | 
    
         
            -
                    major_version = caps[:version] ? caps[:version].split('.')[0] : ''
         
     | 
| 
       258 
     | 
    
         
            -
                    major_version = (major_version != nil) && (major_version != '') && (major_version != '0') ? major_version : nil
         
     | 
| 
       259 
     | 
    
         
            -
                    major_version.nil? ? ('%s' % device) : ('%s %s' % [device, major_version])
         
     | 
| 
       260 
     | 
    
         
            -
                  end
         
     | 
| 
       261 
     | 
    
         
            -
                end
         
     | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
       263 
255 
     | 
    
         
             
                def inferred_environment
         
     | 
| 
       264 
256 
     | 
    
         
             
                  user_agent = driver.user_agent
         
     | 
| 
       265 
257 
     | 
    
         
             
                  if user_agent
         
     | 
| 
       266 
     | 
    
         
            -
                     
     | 
| 
      
 258 
     | 
    
         
            +
                    "useragent:#{user_agent}"
         
     | 
| 
       267 
259 
     | 
    
         
             
                  else
         
     | 
| 
       268 
     | 
    
         
            -
                     
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
      
 260 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 261 
     | 
    
         
            +
                  end
         
     | 
| 
      
 262 
     | 
    
         
            +
                end
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                # Application environment is the environment (e.g., the host OS) which runs the application under test.
         
     | 
| 
      
 265 
     | 
    
         
            +
                #
         
     | 
| 
      
 266 
     | 
    
         
            +
                # Returns:
         
     | 
| 
      
 267 
     | 
    
         
            +
                # +Applitools::Environment+ The application environment.
         
     | 
| 
      
 268 
     | 
    
         
            +
                def app_environment
         
     | 
| 
      
 269 
     | 
    
         
            +
                  os = host_os
         
     | 
| 
      
 270 
     | 
    
         
            +
                  if os.nil?
         
     | 
| 
      
 271 
     | 
    
         
            +
                    EyesLogger.info 'No OS set, checking for mobile OS...'
         
     | 
| 
      
 272 
     | 
    
         
            +
                    if driver.mobile_device?
         
     | 
| 
      
 273 
     | 
    
         
            +
                      platform_name = nil
         
     | 
| 
      
 274 
     | 
    
         
            +
                      EyesLogger.info 'Mobile device detected! Checking device type..'
         
     | 
| 
      
 275 
     | 
    
         
            +
                      if driver.android?
         
     | 
| 
      
 276 
     | 
    
         
            +
                        EyesLogger.info 'Android detected.'
         
     | 
| 
      
 277 
     | 
    
         
            +
                        platform_name = 'Android'
         
     | 
| 
      
 278 
     | 
    
         
            +
                      elsif driver.ios?
         
     | 
| 
      
 279 
     | 
    
         
            +
                        EyesLogger.info 'iOS detected.'
         
     | 
| 
      
 280 
     | 
    
         
            +
                        platform_name = 'iOS'
         
     | 
| 
      
 281 
     | 
    
         
            +
                      else
         
     | 
| 
      
 282 
     | 
    
         
            +
                        EyesLogger.info 'Unknown device type.'
         
     | 
| 
      
 283 
     | 
    
         
            +
                      end
         
     | 
| 
      
 284 
     | 
    
         
            +
                      # We only set the OS if we identified the device type.
         
     | 
| 
      
 285 
     | 
    
         
            +
                      unless platform_name.nil?
         
     | 
| 
      
 286 
     | 
    
         
            +
                        platform_version = driver.platform_version
         
     | 
| 
      
 287 
     | 
    
         
            +
                        if platform_version.nil?
         
     | 
| 
      
 288 
     | 
    
         
            +
                          os = platform_name
         
     | 
| 
      
 289 
     | 
    
         
            +
                        else
         
     | 
| 
      
 290 
     | 
    
         
            +
                          # Notice that Ruby's +split+ function's +limit+ is the number of elements, whereas in Python it is the
         
     | 
| 
      
 291 
     | 
    
         
            +
                          # maximum splits performed (which is why they are set differently).
         
     | 
| 
      
 292 
     | 
    
         
            +
                          major_version = platform_version.split('.', 2)[0]
         
     | 
| 
      
 293 
     | 
    
         
            +
                          os = "#{platform_name} #{major_version}"
         
     | 
| 
      
 294 
     | 
    
         
            +
                        end
         
     | 
| 
      
 295 
     | 
    
         
            +
                        EyesLogger.info "Setting OS: #{os}"
         
     | 
| 
      
 296 
     | 
    
         
            +
                      end
         
     | 
| 
      
 297 
     | 
    
         
            +
                    else
         
     | 
| 
      
 298 
     | 
    
         
            +
                      EyesLogger.info 'No mobile OS detected.'
         
     | 
| 
       271 
299 
     | 
    
         
             
                    end
         
     | 
| 
       272 
300 
     | 
    
         
             
                  end
         
     | 
| 
      
 301 
     | 
    
         
            +
                  # Create and return the environment object.
         
     | 
| 
      
 302 
     | 
    
         
            +
                  Applitools::Environment.new(os, host_app, viewport_size, inferred_environment)
         
     | 
| 
       273 
303 
     | 
    
         
             
                end
         
     | 
| 
       274 
304 
     | 
    
         | 
| 
       275 
305 
     | 
    
         
             
                def start_session
         
     | 
| 
       276 
306 
     | 
    
         
             
                  assign_viewport_size
         
     | 
| 
       277 
307 
     | 
    
         
             
                  self.batch ||= Applitools::BatchInfo.new
         
     | 
| 
       278 
     | 
    
         
            -
                  app_env =  
     | 
| 
      
 308 
     | 
    
         
            +
                  app_env = app_environment
         
     | 
| 
       279 
309 
     | 
    
         
             
                  self.session_start_info = Applitools::StartInfo.new(
         
     | 
| 
       280 
310 
     | 
    
         
             
                      full_agent_id, app_name, test_name, batch, baseline_name, app_env, match_level, nil, branch_name, parent_branch_name
         
     | 
| 
       281 
311 
     | 
    
         
             
                  )
         
     | 
| 
         @@ -94,8 +94,9 @@ class Applitools::MatchWindowTask 
     | 
|
| 
       94 
94 
     | 
    
         
             
                  title = eyes.title
         
     | 
| 
       95 
95 
     | 
    
         
             
                  EyesLogger.debug 'Getting screenshot...'
         
     | 
| 
       96 
96 
     | 
    
         
             
                  screenshot64 = driver.screenshot_as(:base64)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  # We need a reference to the raw bytes of the PNG, which is why we didn't
         
     | 
| 
      
 98 
     | 
    
         
            +
                  # use +Applitools::Utils::ImageUtils.image_from_base64+.
         
     | 
| 
       97 
99 
     | 
    
         
             
                  EyesLogger.debug 'Done! Decoding base64...'
         
     | 
| 
       98 
     | 
    
         
            -
                  # 'encoded', as in 'png'.
         
     | 
| 
       99 
100 
     | 
    
         
             
                  current_screenshot_encoded = Base64.decode64(screenshot64)
         
     | 
| 
       100 
101 
     | 
    
         
             
                  EyesLogger.debug 'Done! Creating image object from PNG...'
         
     | 
| 
       101 
102 
     | 
    
         
             
                  @current_screenshot = ChunkyPNG::Image.from_blob(current_screenshot_encoded)
         
     | 
| 
         @@ -48,11 +48,19 @@ class Applitools::ViewportSize 
     | 
|
| 
       48 
48 
     | 
    
         
             
                  width  = extract_viewport_width
         
     | 
| 
       49 
49 
     | 
    
         
             
                  height = extract_viewport_height
         
     | 
| 
       50 
50 
     | 
    
         
             
                rescue => e
         
     | 
| 
       51 
     | 
    
         
            -
                  EyesLogger.info " 
     | 
| 
      
 51 
     | 
    
         
            +
                  EyesLogger.info "#{__method__}(): Failed to extract viewport size using Javascript: (#{e.message})"
         
     | 
| 
       52 
52 
     | 
    
         
             
                end
         
     | 
| 
       53 
53 
     | 
    
         
             
                if width.nil? || height.nil?
         
     | 
| 
       54 
     | 
    
         
            -
                  EyesLogger.info  
     | 
| 
      
 54 
     | 
    
         
            +
                  EyesLogger.info "#{__method__}(): Using window size as viewport size."
         
     | 
| 
       55 
55 
     | 
    
         
             
                  width, height = *browser_size.values
         
     | 
| 
      
 56 
     | 
    
         
            +
                  width, height = width.ceil, height.ceil
         
     | 
| 
      
 57 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 58 
     | 
    
         
            +
                    if driver.landscape_orientation? && height > width
         
     | 
| 
      
 59 
     | 
    
         
            +
                      width, height = height, width
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  rescue NameError
         
     | 
| 
      
 62 
     | 
    
         
            +
                    # Ignored. This error will occur for web based drivers, since they don't have the "orientation" attribute.
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
       56 
64 
     | 
    
         
             
                end
         
     | 
| 
       57 
65 
     | 
    
         
             
                Applitools::Dimension.new(width,height)
         
     | 
| 
       58 
66 
     | 
    
         
             
              end
         
     | 
| 
         @@ -64,7 +72,7 @@ class Applitools::ViewportSize 
     | 
|
| 
       64 
72 
     | 
    
         
             
                  self.dimension = Struct.new(:width, :height).new(dimension[:width], dimension[:height])
         
     | 
| 
       65 
73 
     | 
    
         
             
                elsif !dimension.respond_to?(:width) || !dimension.respond_to?(:height)
         
     | 
| 
       66 
74 
     | 
    
         
             
                  raise ArgumentError, "expected #{dimension.inspect}:#{dimension.class}" +
         
     | 
| 
       67 
     | 
    
         
            -
                                        
     | 
| 
      
 75 
     | 
    
         
            +
                                       ' to respond to #width and #height, or be a hash with these keys.'
         
     | 
| 
       68 
76 
     | 
    
         
             
                end
         
     | 
| 
       69 
77 
     | 
    
         
             
                self.browser_size = dimension
         
     | 
| 
       70 
78 
     | 
    
         
             
                verify_size(:browser_size)
         
     | 
    
        data/lib/eyes_selenium/utils.rb
    CHANGED
    
    
| 
         @@ -1,21 +1,21 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            =begin
         
     | 
| 
       2 
2 
     | 
    
         
             
            Applitools SDK class.
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
            Provides image compression based on image sequences and deflate
         
     | 
| 
      
 4 
     | 
    
         
            +
            Provides image compression based on image sequences and deflate.
         
     | 
| 
       5 
5 
     | 
    
         
             
            =end
         
     | 
| 
       6 
6 
     | 
    
         
             
            require 'oily_png'
         
     | 
| 
       7 
     | 
    
         
            -
            require 'base64'
         
     | 
| 
       8 
7 
     | 
    
         | 
| 
       9 
8 
     | 
    
         
             
            class Applitools::Utils::ImageDeltaCompressor
         
     | 
| 
       10 
9 
     | 
    
         | 
| 
       11 
10 
     | 
    
         
             
              # Compresses the target image based on the source image.
         
     | 
| 
      
 11 
     | 
    
         
            +
              #
         
     | 
| 
       12 
12 
     | 
    
         
             
              # +target+:: +ChunkyPNG::Canvas+ The image to compress based on the source image.
         
     | 
| 
       13 
13 
     | 
    
         
             
              # +target_encoded+:: +Array+ The uncompressed image as binary string.
         
     | 
| 
       14 
14 
     | 
    
         
             
              # +source+:: +ChunkyPNG::Canvas+ The source image used as a base for compressing the target image.
         
     | 
| 
       15 
15 
     | 
    
         
             
              # +block_size+:: +Integer+ The width/height of each block.
         
     | 
| 
       16 
     | 
    
         
            -
              # 
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
       17 
17 
     | 
    
         
             
              # Returns +String+ The binary result (either the compressed image, or the uncompressed image if the compression
         
     | 
| 
       18 
     | 
    
         
            -
              # is greater in length)
         
     | 
| 
      
 18 
     | 
    
         
            +
              # is greater in length).
         
     | 
| 
       19 
19 
     | 
    
         
             
              def self.compress_by_raw_blocks(target, target_encoded, source, block_size = 10)
         
     | 
| 
       20 
20 
     | 
    
         
             
                # If we can't compress for any reason, return the target image as is.
         
     | 
| 
       21 
21 
     | 
    
         
             
                if source.nil? || (source.height != target.height) || (source.width != target.width)
         
     | 
| 
         @@ -84,7 +84,7 @@ class Applitools::Utils::ImageDeltaCompressor 
     | 
|
| 
       84 
84 
     | 
    
         
             
              ### PRIVATE
         
     | 
| 
       85 
85 
     | 
    
         
             
              private
         
     | 
| 
       86 
86 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
              @@PREAMBLE =  
     | 
| 
      
 87 
     | 
    
         
            +
              @@PREAMBLE = 'applitools'
         
     | 
| 
       88 
88 
     | 
    
         
             
              @@FORMAT_RAW_BLOCKS = 3
         
     | 
| 
       89 
89 
     | 
    
         | 
| 
       90 
90 
     | 
    
         
             
              Dimension = Struct.new(:width, :height)
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            =begin
         
     | 
| 
      
 2 
     | 
    
         
            +
            Applitools SDK class.
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Provides images manipulation functionality.
         
     | 
| 
      
 5 
     | 
    
         
            +
            =end
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'oily_png'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'base64'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module Applitools::Utils::ImageUtils
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              # Creates an image object from the PNG bytes.
         
     | 
| 
      
 12 
     | 
    
         
            +
              # +png_bytes+:: +String+ A binary string of the PNG bytes of the image.
         
     | 
| 
      
 13 
     | 
    
         
            +
              #
         
     | 
| 
      
 14 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 15 
     | 
    
         
            +
              # +ChunkyPNG::Canvas+ An image object.
         
     | 
| 
      
 16 
     | 
    
         
            +
              def self.png_image_from_bytes(png_bytes)
         
     | 
| 
      
 17 
     | 
    
         
            +
                EyesLogger.debug "#{__method__}()"
         
     | 
| 
      
 18 
     | 
    
         
            +
                image = ChunkyPNG::Image.from_blob(png_bytes)
         
     | 
| 
      
 19 
     | 
    
         
            +
                EyesLogger.debug 'Done!'
         
     | 
| 
      
 20 
     | 
    
         
            +
                return image
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
                
         
     | 
| 
      
 23 
     | 
    
         
            +
              # Creates an image instance from a base64 representation of its PNG encoding.
         
     | 
| 
      
 24 
     | 
    
         
            +
              #
         
     | 
| 
      
 25 
     | 
    
         
            +
              # +png_bytes64+:: +String+ The Base64 representation of a PNG image.
         
     | 
| 
      
 26 
     | 
    
         
            +
              #
         
     | 
| 
      
 27 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 28 
     | 
    
         
            +
              # +ChunkyPNG::Canvas+ An image object.
         
     | 
| 
      
 29 
     | 
    
         
            +
              def self.png_image_from_base64(png_bytes64)
         
     | 
| 
      
 30 
     | 
    
         
            +
                EyesLogger.debug "#{__method__}()"
         
     | 
| 
      
 31 
     | 
    
         
            +
                png_bytes = Base64.decode64(png_bytes64)
         
     | 
| 
      
 32 
     | 
    
         
            +
                EyesLogger.debug 'Done!'
         
     | 
| 
      
 33 
     | 
    
         
            +
                return png_image_from_bytes(png_bytes)
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              # Get the raw PNG bytes of an image.
         
     | 
| 
      
 37 
     | 
    
         
            +
              #
         
     | 
| 
      
 38 
     | 
    
         
            +
              # +ChunkyPNG::Canvas+ The image object for which to get the PNG bytes.
         
     | 
| 
      
 39 
     | 
    
         
            +
              #
         
     | 
| 
      
 40 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 41 
     | 
    
         
            +
              # +String+ The PNG bytes of the image.
         
     | 
| 
      
 42 
     | 
    
         
            +
              def self.bytes_from_png_image(image)
         
     | 
| 
      
 43 
     | 
    
         
            +
                EyesLogger.debug "#{__method__}()"
         
     | 
| 
      
 44 
     | 
    
         
            +
                png_bytes = image.to_blob
         
     | 
| 
      
 45 
     | 
    
         
            +
                EyesLogger.debug 'Done!'
         
     | 
| 
      
 46 
     | 
    
         
            +
                return png_bytes
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              # Get the Base64 representation of the raw PNG bytes of an image.
         
     | 
| 
      
 50 
     | 
    
         
            +
              #
         
     | 
| 
      
 51 
     | 
    
         
            +
              # +ChunkyPNG::Canvas+ The image object for which to get the PNG bytes.
         
     | 
| 
      
 52 
     | 
    
         
            +
              #
         
     | 
| 
      
 53 
     | 
    
         
            +
              # Returns:
         
     | 
| 
      
 54 
     | 
    
         
            +
              # +String+ the Base64 representation of the raw PNG bytes of an image.
         
     | 
| 
      
 55 
     | 
    
         
            +
              def self.base64_from_png_image(image)
         
     | 
| 
      
 56 
     | 
    
         
            +
                EyesLogger.debug "#{__method__}()"
         
     | 
| 
      
 57 
     | 
    
         
            +
                png_bytes = bytes_from_png_image(image)
         
     | 
| 
      
 58 
     | 
    
         
            +
                EyesLogger.debug 'Encoding as base64...'
         
     | 
| 
      
 59 
     | 
    
         
            +
                image64 = Base64.encode64(png_bytes)
         
     | 
| 
      
 60 
     | 
    
         
            +
                EyesLogger.debug 'Done!'
         
     | 
| 
      
 61 
     | 
    
         
            +
                return image64
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              # Rotates a matrix 90 deg clockwise or counter clockwise (depending whether num_quadrants is positive or negative,
         
     | 
| 
      
 65 
     | 
    
         
            +
              # respectively).
         
     | 
| 
      
 66 
     | 
    
         
            +
              #
         
     | 
| 
      
 67 
     | 
    
         
            +
              # +image+:: +ChunkyPNG::Canvas+ The image to rotate.
         
     | 
| 
      
 68 
     | 
    
         
            +
              # +num_quadrants+:: +Integer+ The number of rotations to perform. Positive values are used for clockwise rotation
         
     | 
| 
      
 69 
     | 
    
         
            +
              #                   and negative values are used for counter-clockwise rotation.
         
     | 
| 
      
 70 
     | 
    
         
            +
              #
         
     | 
| 
      
 71 
     | 
    
         
            +
              def self.quadrant_rotate!(image, num_quadrants)
         
     | 
| 
      
 72 
     | 
    
         
            +
                rotate_method = num_quadrants > 0 ? image.method('rotate_right!'.to_sym) : image.method('rotate_left!'.to_sym)
         
     | 
| 
      
 73 
     | 
    
         
            +
                (0..(num_quadrants.abs-1)).each { rotate_method.call }
         
     | 
| 
      
 74 
     | 
    
         
            +
                return image
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
    
        data/test_script.rb
    CHANGED
    
    | 
         @@ -14,8 +14,8 @@ begin 
     | 
|
| 
       14 
14 
     | 
    
         
             
              eyes.test(app_name: 'Ruby SDK', test_name: 'Applitools website test', viewport_size: {width: 1024, height: 768}, driver: my_webdriver) do |driver|
         
     | 
| 
       15 
15 
     | 
    
         
             
                driver.get 'http://www.applitools.com'
         
     | 
| 
       16 
16 
     | 
    
         
             
                eyes.check_window('initial')
         
     | 
| 
       17 
     | 
    
         
            -
                eyes.check_region(:css, ' 
     | 
| 
       18 
     | 
    
         
            -
                driver.find_element(:css, ' 
     | 
| 
      
 17 
     | 
    
         
            +
                eyes.check_region(:css, '.pricing', 'Pricing button')
         
     | 
| 
      
 18 
     | 
    
         
            +
                driver.find_element(:css, '.pricing a').click
         
     | 
| 
       19 
19 
     | 
    
         
             
                eyes.check_window('pricing page')
         
     | 
| 
       20 
20 
     | 
    
         
             
              end
         
     | 
| 
       21 
21 
     | 
    
         
             
            ensure
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: eyes_selenium
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 2.9.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Applitools team
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2015- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2015-04-23 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: selenium-webdriver
         
     | 
| 
         @@ -16,14 +16,28 @@ dependencies: 
     | 
|
| 
       16 
16 
     | 
    
         
             
                requirements:
         
     | 
| 
       17 
17 
     | 
    
         
             
                - - ">="
         
     | 
| 
       18 
18 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       19 
     | 
    
         
            -
                    version:  
     | 
| 
      
 19 
     | 
    
         
            +
                    version: 2.45.0
         
     | 
| 
       20 
20 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       21 
21 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       22 
22 
     | 
    
         
             
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       23 
23 
     | 
    
         
             
                requirements:
         
     | 
| 
       24 
24 
     | 
    
         
             
                - - ">="
         
     | 
| 
       25 
25 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       26 
     | 
    
         
            -
                    version:  
     | 
| 
      
 26 
     | 
    
         
            +
                    version: 2.45.0
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: appium_lib
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: 6.0.0
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: 6.0.0
         
     | 
| 
       27 
41 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       28 
42 
     | 
    
         
             
              name: httparty
         
     | 
| 
       29 
43 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -164,6 +178,7 @@ files: 
     | 
|
| 
       164 
178 
     | 
    
         
             
            - lib/eyes_selenium/eyes_logger.rb
         
     | 
| 
       165 
179 
     | 
    
         
             
            - lib/eyes_selenium/utils.rb
         
     | 
| 
       166 
180 
     | 
    
         
             
            - lib/eyes_selenium/utils/image_delta_compressor.rb
         
     | 
| 
      
 181 
     | 
    
         
            +
            - lib/eyes_selenium/utils/image_utils.rb
         
     | 
| 
       167 
182 
     | 
    
         
             
            - lib/eyes_selenium/version.rb
         
     | 
| 
       168 
183 
     | 
    
         
             
            - spec/find_spec.rb
         
     | 
| 
       169 
184 
     | 
    
         
             
            - test_script.rb
         
     |