Class: Percy::Capybara::Loaders::SprocketsLoader

Inherits:
BaseLoader
  • Object
show all
Defined in:
lib/percy/capybara/loaders/sprockets_loader.rb

Overview

Resource loader that loads assets via Sprockets (ie. the Rails asset pipeline).

Direct Known Subclasses

EmberCliRailsLoader

Constant Summary collapse

SKIP_RESOURCE_EXTENSIONS =
[
  '.map', # Ignore source maps.
  '.gz', # Ignore gzipped files.
].freeze
MAX_FILESIZE_BYTES =

15 MB.

15 * 1024**2

Constants inherited from BaseLoader

BaseLoader::URL_REGEX

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from BaseLoader

#_find_files, #_resources_from_dir, #_uri_join

Constructor Details

#initialize(options = {}) ⇒ SprocketsLoader

Returns a new instance of SprocketsLoader.



22
23
24
25
26
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 22

def initialize(options = {})
  @sprockets_environment = options[:sprockets_environment]
  @sprockets_options = options[:sprockets_options]
  super(options)
end

Instance Attribute Details

#pageObject (readonly)

Returns the value of attribute page.



12
13
14
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 12

def page
  @page
end

#sprockets_environmentObject (readonly)

Returns the value of attribute sprockets_environment.



13
14
15
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 13

def sprockets_environment
  @sprockets_environment
end

#sprockets_optionsObject (readonly)

Returns the value of attribute sprockets_options.



14
15
16
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 14

def sprockets_options
  @sprockets_options
end

Instance Method Details

#_asset_logical_pathsObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 80

def _asset_logical_paths
  if _rails && _rails.application.respond_to?(:precompiled_assets)
    _rails.application.precompiled_assets
  else
    # Re-implement the same technique that "rake assets:precompile" uses to generate the
    # list of asset paths to include in compiled assets. https://goo.gl/sy2R4z
    # We can't just use environment.each_logical_path without any filters, because then
    # we will attempt to compile assets before they're rendered (such as _mixins.css).
    precompile_list = sprockets_options.precompile
    logical_paths = sprockets_environment.each_logical_path(*precompile_list).to_a
    logical_paths += precompile_list.flatten.select do |filename|
      Pathname.new(filename).absolute? if filename.is_a?(String)
    end
    logical_paths.uniq
  end
end

#_railsObject



76
77
78
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 76

def _rails
  Rails if defined?(Rails)
end

#build_resourcesObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 32

def build_resources
  resources = []
  loaded_resource_urls = Set.new

  # Load resources from the asset pipeline.
  _asset_logical_paths.each do |logical_path|
    next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(logical_path))

    asset = sprockets_environment.find_asset(logical_path)

    # Skip large files, these are hopefully downloads and not used in page rendering.
    next if asset.length > MAX_FILESIZE_BYTES

    content = asset.to_s
    sha = Digest::SHA256.hexdigest(content)

    if defined?(ActionController)
      # Ask Rails where this asset is (this handles asset_hosts, digest paths, etc.).
      resource_url = ActionController::Base.helpers.asset_path(logical_path)
    else
      # TODO: more robust support for Sprockets usage outside Rails, ie Sinatra.
      # How do we find the correct path in that case?
      path = sprockets_options.digest ? asset.digest_path : logical_path
      resource_url = Addressable::URI.escape("/assets/#{path}")
    end

    next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(resource_url))

    loaded_resource_urls.add(resource_url)
    resources << Percy::Client::Resource.new(resource_url, sha: sha, content: content)
  end

  # Load resources from the public/ directory, if a Rails app.
  if _rails
    public_path = _rails.public_path.to_s
    resources += _resources_from_dir(public_path).reject do |resource|
      # Skip precompiled files already included via the asset pipeline.
      loaded_resource_urls.include?(resource.resource_url)
    end
  end

  resources
end

#snapshot_resourcesObject



28
29
30
# File 'lib/percy/capybara/loaders/sprockets_loader.rb', line 28

def snapshot_resources
  [root_html_resource] + iframes_resources
end