Class: Percy::Capybara::Loaders::BaseLoader

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

Direct Known Subclasses

FilesystemLoader, NativeLoader, SprocketsLoader

Constant Summary collapse

URL_REGEX =

Modified version of Diego Perini’s URL regex. gist.github.com/dperini/729294

Regexp.new(
  # protocol identifier
  '((?:https?:)?//)' \
  '(' +
    # IP address exclusion
    # private & local networks
    '(?!(?:10|127)(?:\\.\\d{1,3}){3})' \
    '(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})' \
    '(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})' +
    # IP address dotted notation octets
    # excludes loopback network 0.0.0.0
    # excludes reserved space >= 224.0.0.0
    # excludes network & broacast addresses
    # (first & last IP address of each class)
    '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' \
    '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' \
    '(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' \
  '|' +
    # host name
    '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
    # domain name
    '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' \
  ')' +
  # port number
  '(:\\d{2,5})?' +
  # resource path
  "(/[^\\s\"']*)?",
)
SKIP_RESOURCE_EXTENSIONS =
[
  '.map', # Ignore source maps.
  '.gz', # Ignore gzipped files.
].freeze
MAX_FILESIZE_BYTES =

15 MB.

15 * 1024**2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ BaseLoader

Returns a new instance of BaseLoader.

Parameters:

  • page (Capybara::Session)

    The Capybara page.

  • include_iframes (bool)

    Include iframes in the snapshot



49
50
51
52
# File 'lib/percy/capybara/loaders/base_loader.rb', line 49

def initialize(options = {})
  @page = options[:page]
  @include_iframes = options[:include_iframes] || false
end

Instance Attribute Details

#pageObject (readonly)

Returns the value of attribute page.



45
46
47
# File 'lib/percy/capybara/loaders/base_loader.rb', line 45

def page
  @page
end

Instance Method Details

#_find_files(*paths) ⇒ Object

A simplified version of Find.find that only returns files and follows symlinks.



146
147
148
149
150
151
# File 'lib/percy/capybara/loaders/base_loader.rb', line 146

def _find_files(*paths)
  paths.flatten.map do |path|
    path = Pathname.new(path)
    path.file? ? [path.to_s] : _find_files(path.children)
  end.flatten
end

#_resources_from_dir(root_dir, base_url: '/') ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/percy/capybara/loaders/base_loader.rb', line 125

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

  _find_files(root_dir).each do |path|
    # Skip certain extensions.
    next if SKIP_RESOURCE_EXTENSIONS.include?(File.extname(path))
    # 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

  resources
end

#_uri_join(*paths) ⇒ Object



153
154
155
156
157
# File 'lib/percy/capybara/loaders/base_loader.rb', line 153

def _uri_join(*paths)
  # We must swap File::SEPARATOR for '/' here because on Windows File.join
  # will use backslashes and this is a URL.
  File.join(paths).gsub(File::SEPARATOR, '/')
end

#build_resourcesObject

Raises:

  • (NotImplementedError)


54
55
56
# File 'lib/percy/capybara/loaders/base_loader.rb', line 54

def build_resources
  raise NotImplementedError, 'subclass must implement abstract method'
end

#snapshot_resourcesObject

Raises:

  • (NotImplementedError)


58
59
60
# File 'lib/percy/capybara/loaders/base_loader.rb', line 58

def snapshot_resources
  raise NotImplementedError, 'subclass must implement abstract method'
end