applitools / Eyes.Selenium.Ruby

Deprecated! Applitools Eyes Ruby SDK for Selenium WebDriver
Other
11 stars 11 forks source link

Allow check_region to accept an Element instead of a Locator #30

Closed tommyh closed 8 years ago

tommyh commented 8 years ago

Right now, when I call check_region I have to pass it a locator, eg:

eyes.check_region(:css, "#player .tout-player .play-button", "Play Button")

I would prefer if I could just pass in a Selenium::WebDriver::Element object directly.

My usecase: I am using SitePrism for my page objects. Because the page object model has objects for elements, I already have reference to the element which I want the screenshot of. For example:

class Player < SitePrism::Section
  element :play_button, ".tout-player .play-button"
end

class Vdp < SitePrism::Page
  set_url "http://player.tout.com/tout{/tout_uid}"

  section :large_player, Player, "#player"
end

So I'd like to be able to write the following:

@vdp = Vdp.new
@vdp.load
eyes.check_region(:element, @vdp.large_player.play_button.root_element.native, "Play Button")

Note: .root_element.native is how you get the Selenium Element for a Capybara Node Element.

What I'm doing now is to duplicating the logic of the css selector between my page objects and the check_region call. I could put the selector in a variable which I could share (to DRY it up a bit), but this only helps with simple cases where my child selector is unique. If my page object "section" appears multiple times on the page, I have to make sure my scoping logic is exactly the same between my page objects and my check_region calls, which could get messy.

I took a stab at implementing the feature (my goal was to to write a pull request for it), but I got stuck on an error which I have little insight into.

Here's what I tried todo:

1) I noticed this is the code, which finds the element you want the screenshot of: https://github.com/applitools/Eyes.Selenium.Ruby/blob/6377b801b787031c56f25165daa4d1f5666a9391/lib/applitools/eyes.rb#L199

2) I modified this:

Applitools::EyesLogger.debug 'Finding element...'
element_to_check = driver.find_element(how, what)

to this:

    if(how == :element)
      element_to_check = what
    else
      Applitools::EyesLogger.debug 'Finding element...'
      element_to_check = driver.find_element(how, what)
    end

3) When I actually use my modified code, the check_region method operates just fine, but there is a call to the applitools backend and the backend returns a 500 error. This is where I got stuck. Is my issue immediately obvious to you? Is it never going to work for some limitation which you know of?

Toms-Air:Ruby-RSpec-Capybara-SauceGem (master) $ bundle exec rspec spec/
****** DEBUG: @page.large_player.root_element.native is #<Selenium::WebDriver::Element:0x..fb4a613ddfad14ec2 id="{a1024b4f-c807-894e-8e0c-62095dc7371f}">
F

Failures:

  1) Video Destination Page should have a large player which is playable
     Got 0 failures and 2 other errors:

     1.1) Failure/Error: eyes.check_region(:element, @page.large_player.root_element.native, "Player", 10)

          Applitools::EyesError:
            Request failed: 500
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/base/server_connector.rb:47:in `match_window'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/method_tracer.rb:12:in `call'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/method_tracer.rb:12:in `block in trace_method'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/selenium/match_window_task.rb:70:in `run_with_intervals'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/selenium/match_window_task.rb:34:in `match_window'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:415:in `check_region_'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:212:in `check_region'
          # ./spec/features/vdp_spec.rb:19:in `block (2 levels) in <top (required)>'

     1.2) Failure/Error: @eyes.close

          Applitools::TestFailedError:
            'Video Destination Page should have a large player which is playable' of 'tom test 5'. see details at https://eyes.applitools.com/app/sessions/251946259711519?accountId=gnGFFil3pkWoUkHlNvo3QA~~
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:265:in `close'
          # ./spec/helpers/applitools_eyes_helper.rb:30:in `close_eyes'
          # ./spec/spec_helper.rb:39:in `block (2 levels) in <top (required)>'

Finished in 26.24 seconds (files took 2.22 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/features/vdp_spec.rb:4 # Video Destination Page should have a large player which is playable

Thanks for your time, I really appreciate it.

Tom

danielputerman commented 8 years ago

Your suggested implementation seems valid, though I haven't tried it inside Capybara. Can you please send me the logs? You activate logging by adding the following after you created the Eyes instance (I'm assuming it's named 'eyes'): eyes.log_handler = Logger.new(STDOUT)

Thanks for the feedback!

tommyh commented 8 years ago

Sure thing. Thanks for the help.

Here is the rspec log w/ eyes logging:

Toms-Air:Ruby-RSpec-Capybara-SauceGem (master) $ bundle exec rspec spec/features/vdp_spec.rb:4
Run options: include {:locations=>{"./spec/features/vdp_spec.rb"=>[4]}}
@@@ Applitools::Eyes.new
@@@ Setting eyes options
@@@ eyes.open
D, [2016-02-23T23:00:13.397032 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:13.398168 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#api_key
@@@ eyes.open finished
@@@ before eyes.check_region
D, [2016-02-23T23:00:29.190861 #68750] DEBUG -- : check_region called
D, [2016-02-23T23:00:29.190982 #68750] DEBUG -- : Starting session...
I, [2016-02-23T23:00:29.240817 #68750]  INFO -- : No OS set, checking for mobile OS...
I, [2016-02-23T23:00:29.240946 #68750]  INFO -- : No mobile OS detected.
D, [2016-02-23T23:00:29.255476 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#start_session
D, [2016-02-23T23:00:29.255606 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#endpoint_url
D, [2016-02-23T23:00:29.255651 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#endpoint_url
D, [2016-02-23T23:00:29.257080 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#post
D, [2016-02-23T23:00:29.257196 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#request
D, [2016-02-23T23:00:29.266289 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:29.266406 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:30.700605 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#request
D, [2016-02-23T23:00:30.700786 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#post
D, [2016-02-23T23:00:30.701002 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#start_session
D, [2016-02-23T23:00:30.701135 #68750] DEBUG -- : Done! Creating match window task...
D, [2016-02-23T23:00:30.701196 #68750] DEBUG -- : Done!
D, [2016-02-23T23:00:30.701237 #68750] DEBUG -- : Done! Getting element location...
D, [2016-02-23T23:00:30.720524 #68750] DEBUG -- : Done! Getting element size...
D, [2016-02-23T23:00:30.756422 #68750] DEBUG -- : Done! Creating region...
D, [2016-02-23T23:00:30.756552 #68750] DEBUG -- : Done! Checking region...
I, [2016-02-23T23:00:30.756612 #68750]  INFO -- : check_region_('Player', 10)
D, [2016-02-23T23:00:30.756653 #68750] DEBUG -- : Starting match task...
D, [2016-02-23T23:00:30.756696 #68750] DEBUG -- : Retry timeout set to: 10
D, [2016-02-23T23:00:30.756737 #68750] DEBUG -- : Matching with intervals...
D, [2016-02-23T23:00:30.756799 #68750] DEBUG -- : Preparing match data...
D, [2016-02-23T23:00:30.871261 #68750] DEBUG -- : Getting screenshot...
D, [2016-02-23T23:00:31.262843 #68750] DEBUG -- : Waiting before screenshot: 0.1 seconds...
D, [2016-02-23T23:00:31.366126 #68750] DEBUG -- : Finished waiting.
D, [2016-02-23T23:00:35.988522 #68750] DEBUG -- : -> Applitools::Utils::ImageUtils#png_image_from_base64
D, [2016-02-23T23:00:36.010179 #68750] DEBUG -- : -> Applitools::Utils::ImageUtils#png_image_from_bytes
D, [2016-02-23T23:00:36.603080 #68750] DEBUG -- : <- Applitools::Utils::ImageUtils#png_image_from_bytes
D, [2016-02-23T23:00:36.603194 #68750] DEBUG -- : <- Applitools::Utils::ImageUtils#png_image_from_base64
D, [2016-02-23T23:00:37.076109 #68750] DEBUG -- : -> Applitools::Utils::ImageUtils#quadrant_rotate!
D, [2016-02-23T23:00:37.076843 #68750] DEBUG -- : <- Applitools::Utils::ImageUtils#quadrant_rotate!
D, [2016-02-23T23:00:37.127971 #68750] DEBUG -- : -> Applitools::Utils::ImageUtils#bytes_from_png_image
D, [2016-02-23T23:00:37.749637 #68750] DEBUG -- : <- Applitools::Utils::ImageUtils#bytes_from_png_image
D, [2016-02-23T23:00:37.749777 #68750] DEBUG -- : Done! Creating image object from PNG...
D, [2016-02-23T23:00:38.700626 #68750] DEBUG -- : Done!
D, [2016-02-23T23:00:38.700781 #68750] DEBUG -- : Calculating clipped region...
D, [2016-02-23T23:00:38.700858 #68750] DEBUG -- : Done! Cropping region...
D, [2016-02-23T23:00:38.700916 #68750] DEBUG -- : Done! Creating cropped image object...
D, [2016-02-23T23:00:38.703982 #68750] DEBUG -- : Done!
D, [2016-02-23T23:00:38.704605 #68750] DEBUG -- : Compressing screenshot...
D, [2016-02-23T23:00:38.704749 #68750] DEBUG -- : -> Applitools::Utils::ImageDeltaCompressor#compress_by_raw_blocks
D, [2016-02-23T23:00:38.704961 #68750] DEBUG -- : <- Applitools::Utils::ImageDeltaCompressor#compress_by_raw_blocks
D, [2016-02-23T23:00:38.705114 #68750] DEBUG -- : Done! Creating AppOuptut...
D, [2016-02-23T23:00:38.705225 #68750] DEBUG -- : Handling user inputs...
I, [2016-02-23T23:00:38.705354 #68750]  INFO -- : Triggers ignored: no previous window checked
D, [2016-02-23T23:00:38.705400 #68750] DEBUG -- : Creating MatchWindowData object..
D, [2016-02-23T23:00:38.705492 #68750] DEBUG -- : Done creating MatchWindowData object!
D, [2016-02-23T23:00:38.705590 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#match_window
D, [2016-02-23T23:00:38.706172 #68750] DEBUG -- : Sending match data...
D, [2016-02-23T23:00:38.706547 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#endpoint_url
D, [2016-02-23T23:00:38.707088 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#endpoint_url
D, [2016-02-23T23:00:38.709243 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#post
D, [2016-02-23T23:00:38.709545 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#request
D, [2016-02-23T23:00:38.710674 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:38.711086 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:40.122931 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#request
D, [2016-02-23T23:00:40.123032 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#post
@@@ before eyes.close
D, [2016-02-23T23:00:40.123324 #68750] DEBUG -- : Ending server session...
D, [2016-02-23T23:00:40.123379 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#stop_session
D, [2016-02-23T23:00:40.123427 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#endpoint_url
D, [2016-02-23T23:00:40.123468 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#endpoint_url
D, [2016-02-23T23:00:40.125163 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#long_delete
D, [2016-02-23T23:00:40.125227 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#long_request
D, [2016-02-23T23:00:40.125316 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#request
D, [2016-02-23T23:00:40.125675 #68750] DEBUG -- : -> Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:40.125723 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#api_key
D, [2016-02-23T23:00:40.500783 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#request
D, [2016-02-23T23:00:40.501558 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#long_request
D, [2016-02-23T23:00:40.501865 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#long_delete
D, [2016-02-23T23:00:40.502303 #68750] DEBUG -- : <- Applitools::Base::ServerConnector#stop_session
D, [2016-02-23T23:00:40.502622 #68750] DEBUG -- : Results: Existing test [ steps: 3, matches: 0, mismatches: 0, missing: 3 ], URL: https://eyes.applitools.com/app/sessions/251946003575274?accountId=gnGFFil3pkWoUkHlNvo3QA~~
I, [2016-02-23T23:00:40.502968 #68750]  INFO -- : --- Failed test ended. See details at https://eyes.applitools.com/app/sessions/251946003575274?accountId=gnGFFil3pkWoUkHlNvo3QA~~
F

Failures:

  1) Video Destination Page should have a large player which is playable
     Got 0 failures and 2 other errors:

     1.1) Failure/Error: @eyes.check_region(:element, @vdp.large_player.root_element.native, "Player", 10)

          Applitools::EyesError:
            Request failed: 500
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/base/server_connector.rb:47:in `match_window'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/method_tracer.rb:12:in `call'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/method_tracer.rb:12:in `block in trace_method'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/selenium/match_window_task.rb:70:in `run_with_intervals'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/selenium/match_window_task.rb:34:in `match_window'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:415:in `check_region_'
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:212:in `check_region'
          # ./spec/features/vdp_spec.rb:9:in `block (2 levels) in <top (required)>'

     1.2) Failure/Error: @eyes.close

          Applitools::TestFailedError:
            'Video Destination Page should have a large player which is playable' of 'tom test 6'. see details at https://eyes.applitools.com/app/sessions/251946003575274?accountId=gnGFFil3pkWoUkHlNvo3QA~~
          # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:265:in `close'
          # ./spec/helpers/applitools_eyes_helper.rb:48:in `close_eyes'
          # ./spec/spec_helper.rb:39:in `block (2 levels) in <top (required)>'

Finished in 35.05 seconds (files took 3.79 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/features/vdp_spec.rb:4 # Video Destination Page should have a large player which is playable

Here are some of the relevant code portions:

module ApplitoolsEyesHelpers
  def setup_eyes(example, driver, app_name)
    puts "@@@ Applitools::Eyes.new"
    @eyes = Applitools::Eyes.new
    puts "@@@ Setting eyes options"
    @eyes.api_key = "MY_API_KEY_HERE"
    @eyes.force_fullpage_screenshot = true
    @eyes.log_handler = Logger.new(STDOUT)

    puts "@@@ eyes.open"
    @driver = @eyes.open(
      app_name: app_name,
      test_name: example.full_description,
      driver: driver
    )
    puts "@@@ eyes.open finished"
  end

  def close_eyes
    puts "@@@ before eyes.close"
    @eyes.close
    puts "@@@ after eyes.close"
  end

end
RSpec.configure do |config|
  config.include ApplitoolsEyesHelpers

  config.before(:each) do |example|
    setup_eyes(example, Capybara.current_session.driver.browser, "tom test 6")
  end

  config.after(:each) do |example|
    close_eyes
  end

  config.include Capybara::DSL
  config.include Capybara::RSpecMatchers
end
require "spec_helper"

describe "Video Destination Page", :sauce => false do
  it "should have a large player which is playable" do
    @vdp = Vdp.new
    @vdp.go_to_homepage

    puts "@@@ before eyes.check_region"
    @eyes.check_region(:element, @vdp.large_player.root_element.native, "Player", 10)
    puts "@@@ after eyes.check_region"
  end
end
tommyh commented 8 years ago

Good news, I believe I solved the issue.

1) Turns out my original check_region code works fine. I will open a pull request with this code. :)

2) The reason for the 500 error was user error. Turns out the region I was trying to capture was an element which was a collapsed div, so it had a height of 0. That's why the selenium api was returning a 500 error. (Note: it's child div had a height, so I wasn't way off but it makes sense why it was blowing up).

It might be nice to have a validation in the gem which throws an error when the region has a 0 width or height. Would you be against me the following validation to the check_region method? If you are supportive of it, 2 following questions: i) want me to make a different pull request? or same? ii) what would you like the error message copy to be?

    size = element_to_check.size
    raise Applitools::EyesError.new('Region must have a non-zero width.') if size.width == 0
    raise Applitools::EyesError.new('Region must have a non-zero height.') if size.height == 0

example in rspec:

  1) Video Destination Page should have a large player which is playable
     Failure/Error: @eyes.check_region(:css, "#player", "Player", 10)

     Applitools::EyesError:
       Region must have a non-zero height.
     # /Users/tom/workspace/Eyes.Selenium.Ruby/lib/applitools/eyes.rb:211:in `check_region'
     # ./spec/features/vdp_spec.rb:13:in `block (2 levels) in <top (required)>'
danielputerman commented 8 years ago

@tommyh Nice catch! :) 1) One pull request is fine. 2) Please use: raise Applitools::EyesError.new("Invalid region size: #{size}") if size.width <=0 || size.height <=0