percy / percy-capybara

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

What is the preferred way to define/use custom loaders? #66

Closed tangrufus closed 5 years ago

tangrufus commented 5 years ago

We want to use Bedorck with Percy::Anywhere. However, the :filesystem loader is loading too many resources.


Currenly code that doesn't allow custom loader:

https://github.com/percy/percy-capybara/blob/5865d54b81eac27ffc74c839eef7425a361d6f89/lib/percy/capybara/anywhere.rb#L25

https://github.com/percy/percy-capybara/blob/5865d54b81eac27ffc74c839eef7425a361d6f89/lib/percy/capybara/client.rb#L84-L123


Here is my current workaorund - monkey patch the :filesystem loader:

module Percy
  module Capybara
    module Loaders
      class FilesystemLoader < BaseLoader
        SKIP_RESOURCE_EXTENSIONS = [
          '.gz', # Ignore gzipped files.
          '.htm',
          '.html',
          '.json',
          '.lock',
          '.log',
          '.map', # Ignore source maps.
          '.md',
          '.php',
          '.phtml',
          '.rar',
          '.rb',
          '.sql',
          '.txt',
          '.xml',
          '.zip',
        ].freeze

        SKIP_RESOURCE_BASENAMES = [
          '.DS_Store',
          '.editorconfig',
          '.eslintrc.js',
          '.gitignore',
        ].freeze

        RESOURCE_PATHS = [
          '/app/themes',
          '/app/plugins',
          '/app/mu-plugins',
          '/app/uploads',
          '/wp',
        ].freeze

        SKIP_RESOURCE_PATHS = [
          '/.cache-loader/',
          '/.cache/',
          '/.caches/',
          '/.git/',
          '/build/',
          '/cache/',
          '/caches/',
          '/doc/',
          '/docs/',
          '/log/',
          '/logs/',
          '/node_modules/',
          '/tmp/',
          '/vendor/',
          '/wp/wp-content/themes/',
          'resources/assets',
        ].freeze

        def _resources_from_dir(root_dir, base_url: '/')
          resources = []

          RESOURCE_PATHS.each do |resource_path|
            _find_files(root_dir + resource_path).each do |path|
              next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(path))
              next if SKIP_RESOURCE_BASENAMES.include?(File.basename(path))

              next if SKIP_RESOURCE_PATHS.any? { |skip| path.include?(skip) }

              # Skip large files, these are hopefully downloads and not used in page rendering.
              next if File.size(path) > MAX_FILESIZE_BYTES

              # Replace the assets_dir with the base_url to generate the resource_url
              resource_url = _uri_join(base_url, path.sub(root_dir.to_s, ''))

              sha = Digest::SHA256.hexdigest(File.read(path))

              resources << Percy::Client::Resource.new(resource_url, sha: sha, path: path)
            end
          end

          resources
        end
      end
    end
  end
end

What is the preferred way to define/use custom loaders?

The goal is to:

my_loader = MyLoader.new(some_options)
# Maybe another method
Percy::Capybara.use_loader(my_loader)

Percy::Capybara::Anywhere.run(xxx, yyy, zzz)  do|page|
  #...
end
tangrufus commented 5 years ago

For those having the same question, I packaged my workaorund as a gem

djones commented 5 years ago

Hi @TangRufus, starting from version 4.x of the percy-capybara gem, you won't need to establish any loader at all. We've removed the need for them!

You mentioned:

the :filesystem loader is loading too many resources.

With the new 4.x based version, we capture only the resources used in your snapshots and nothing else.

We've published an upgrade guide from v3 to v4, take a look when you get a moment.