percy / percy-capybara

Visual testing for Capybara with Percy.
https://docs.percy.io/docs/capybara
MIT License
45 stars 23 forks source link

Documentation around loaders #67

Closed sdhull closed 3 years ago

sdhull commented 5 years ago

Obviously I can read the source (and I'm about to, right after this), but it seems like a very core piece of this library is the loader, and it would be useful to have an overview of what's available, what the options are and how they work.

Thanks! Looking forward to getting snapshots working.

sdhull commented 5 years ago

We have a fairly weird spec setup. Assets are not in Rails but in external ember apps. I've updated to Percy::Capybara.use_loader(:native_loader, include_iframes: true) but debug still says Using sprockets_loader to discover assets.

For good measure I also tried Percy::Capybara.use_loader(:native, include_iframes: true) but no luck.

Should I skip trying to get the native loader working and figure out how to resolve paths to the compiled ember apps' /assets dirs?

Robdel12 commented 5 years ago

Hey @sdhull! Thanks for opening an issue. I agree we don't surface API docs very well, but we do have them on Ruby doc for this gem. Here's the API docs for the different loaders: https://www.rubydoc.info/gems/percy-capybara/Percy/Capybara/Loaders

Are you using ember-cli-rails? Does the ember app have it's own test suite or are you looking to test the rails + ember app together?

sdhull commented 5 years ago

@Robdel12 we are not using ember-cli-rails.

The ember apps have some tests but we get the most confidence from integration tests where we boot all our servers (4 altogether) and test everything working together. These tests are written in Capybara in our API server, but we boot test instances (of the other 3 servers) locally & in CircleCI prior to starting the test run.

The API server has zero of the assets needed during these runs.

sdhull commented 5 years ago

But like look at the documentation for use_loader

Is it intended to be called with an instance of a loader (I'm guessing no). Is it intended to be called before or after or instead of initialize_build?

Docs imply that use_loader wants symbols like :something_loader however source seems to indicate it's looking for symbols without the trailing _loader, but perhaps I missed a step where :native_loader is transformed into :native?

tl;dr -- getting started with native loader that pulls resources from the page source should be easy. IMO it should be default, but I understand there's a tradeoff here between "reliable" vs "fast" vs "reliable in non-js-envs" although I don't really understand why you can't get the page body in ruby, parse with Nokogiri and fetch all the assets that way

sdhull commented 5 years ago

well I got percy initialized with the native loader (it says "using custom loader"):

  config.before(:suite) do
    Percy::Capybara.use_loader(Percy::Capybara::Loaders::NativeLoader, asset_hostnames: test_domains, include_iframes: true)
    Percy::Capybara.initialize_build
  end

But it blows up, apparently trying to get an image that is embedded as a data url.

URI::InvalidURIError:
  bad URI(is not URI?): data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/rfc3986_parser.rb:67:in `split'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/rfc3986_parser.rb:73:in `parse'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/rfc3986_parser.rb:117:in `convert_to_uri'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/generic.rb:1101:in `merge'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/rfc3986_parser.rb:89:in `inject'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/rfc3986_parser.rb:89:in `join'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/2.5.0/uri/common.rb:275:in `join'
# /Users/stevehull/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/percy-capybara-3.2.0/lib/percy/capybara/loaders/native_loader.rb:142:in `block in _get_image_resources'

Looks like the test against DATA_URL_REGEX needs to be a few lines higher.

Robdel12 commented 5 years ago

Hey Steve! We've been hard at work eliminating the need for file loaders entirely. We know that's pretty painful part of integrating SDKs and our newer SDKs do asset discovery automatically. We've recently shipped a new beta version of this SDK to bring that automatic asset discovery over (https://github.com/percy/percy-capybara/pull/69). Here's the docs for migrating: https://docs.percy.io/v1/docs/migrating-from-percy-capybara-v3-to-v4

I know you had a hard time with integrating Percy last go around, but if you decide to give it another shot it should be much easier! I'd love to hear if there are any issues if you do give the new version a try. It's currently published as a beta: 4.0.0.pre.beta2

sdhull commented 5 years ago

@Robdel12 if you would like to restart my trial period, I'd be happy to give it a spin. I never got it working before.

Robdel12 commented 5 years ago

No problem! I've extended it for you

sdhull commented 5 years ago

Well that's much better! Tiny note on docs/setup: In your Gemfile, you should specify gem 'percy-capybara', '~>4.0.0.pre.beta2', require: 'percy' (or do require 'percy' in your rails_helper.rb)

Only problem now is that iframes are not working 😦(contrary to comment in the PR that iframes will work fine)

Robdel12 commented 5 years ago

Gotcha! Thank you for giving that a whirl. We'll update the docs & I see what's going on with the iframes. Those are interesting. We'll have to have a little internal discussion & figure out how to handle those. Basically since it's an iframe with a local URL I think we'll need to take another DOM snapshot & do asset discovery on that content -- but I'm not quite sure.

sdhull commented 5 years ago

@Robdel12

I think we'll need to take another DOM snapshot & do asset discovery on that content

That sounds like the right approach to me. Please keep me apprised on that

sdhull commented 5 years ago

@Robdel12

Those are interesting

lol yeah I suspect we have one of the more outlandish testing setups out there. It just occurred to me that we could probably do within_iframe(iframe) { Percy.snapshot(page, name: 'iframe') } however it would be much better if the iframe was rendered properly in place.

Robdel12 commented 5 years ago

Ha! This is actually a pretty sane testing setup from what I've seen. iframes can be difficult to handle but I think it's solvable! We're discussing different options now 😊 I'd be really curious to see what happens if you tried within_iframe(iframe) { Percy.snapshot(page, name: 'iframe') }. It will end up as a different snapshot, which is 👎 imo.

sdhull commented 5 years ago

haha I had typed out a comment yesterday saying "I bet I could do within_frame(iframe)..." but then I deleted it because that's not terribly useful for us (being a different snapshot)—as you clearly anticipated 😉

sdhull commented 5 years ago

We do spawn new tabs and snapshot those using within_window so no reason to think within_frame would work any differently