percy-cli 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/bin/percy +2 -1
- data/lib/percy/cli/snapshot.rb +212 -0
- data/lib/percy/cli/version.rb +2 -2
- data/lib/percy/cli.rb +59 -2
- data/percy-cli.gemspec +4 -0
- data/spec/percy/cli/snapshot_spec.rb +107 -0
- data/spec/percy/cli/testdata/css/base.css +4 -0
- data/spec/percy/cli/testdata/css/test with spaces.css +1 -0
- data/spec/percy/cli/testdata/css/unrelated-no-extension +0 -0
- data/spec/percy/cli/testdata/images/jellybeans.png +0 -0
- data/spec/percy/cli/testdata/index.html +19 -0
- data/spec/percy/cli/testdata/subdir/test.html +1 -0
- data/spec/spec_helper.rb +34 -0
- metadata +78 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a79b07a50003692a4126836dca74ca72787c479c
|
4
|
+
data.tar.gz: 44b4607a5fe3267aae10e772c7b7057f33ded2eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29b2632be605f99a12265a798b7afb40552934bc7445f514a48723ed9842d84672d1524a2f7f1f32fdc1f2615043ed96d14bdb526c3165961a03a0e5590a4549
|
7
|
+
data.tar.gz: 14b7f5941ca563a9bf5c3df841638a162d5c16dd3e3ede57fc644e9fe1190d39ba63dc6e10893f6e6a1e3a644c387e6f652a0bad0f57b0a1035b0b829cd57639
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/bin/percy
CHANGED
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'find'
|
2
|
+
require 'digest'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Percy
|
6
|
+
class Cli
|
7
|
+
module Snapshot
|
8
|
+
# Static resource types that an HTML file might load and that we want to upload for rendering.
|
9
|
+
STATIC_RESOURCE_EXTENSIONS = [
|
10
|
+
'.css', '.jpg', '.jpeg', '.gif', '.ico', '.png', '.bmp', '.pict', '.tif', '.tiff', '.ttf',
|
11
|
+
'.eot', '.woff', '.otf', '.svg', '.svgz', '.webp', '.ps',
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
DEFAULT_SNAPSHOTS_REGEX = /\.(html|htm)$/
|
15
|
+
|
16
|
+
# Modified version of Diego Perini's URL regex. https://gist.github.com/dperini/729294
|
17
|
+
REMOTE_URL_REGEX_STRING = (
|
18
|
+
# protocol identifier
|
19
|
+
"(?:(?:https?:)?//)" +
|
20
|
+
"(?:" +
|
21
|
+
# IP address exclusion
|
22
|
+
# private & local networks
|
23
|
+
"(?!(?:10|127)(?:\\.\\d{1,3}){3})" +
|
24
|
+
"(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +
|
25
|
+
"(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
|
26
|
+
# IP address dotted notation octets
|
27
|
+
# excludes loopback network 0.0.0.0
|
28
|
+
# excludes reserved space >= 224.0.0.0
|
29
|
+
# excludes network & broacast addresses
|
30
|
+
# (first & last IP address of each class)
|
31
|
+
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
|
32
|
+
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
|
33
|
+
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
|
34
|
+
"|" +
|
35
|
+
# host name
|
36
|
+
"(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
|
37
|
+
# domain name
|
38
|
+
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
|
39
|
+
# TLD identifier
|
40
|
+
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
|
41
|
+
")" +
|
42
|
+
# port number
|
43
|
+
"(?::\\d{2,5})?" +
|
44
|
+
# resource path
|
45
|
+
"(?:/[^\\s\"']*)?"
|
46
|
+
)
|
47
|
+
HTML_REMOTE_URL_REGEX = Regexp.new("<link.*?href=['\"](" + REMOTE_URL_REGEX_STRING + ")")
|
48
|
+
|
49
|
+
# Match all url("https://...") calls, with whitespace and quote variatinos.
|
50
|
+
CSS_REMOTE_URL_REGEX = Regexp.new(
|
51
|
+
"url\\s*\\([\"'\s]*(" + REMOTE_URL_REGEX_STRING + ")[\"'\s]*\\)"
|
52
|
+
)
|
53
|
+
|
54
|
+
def run_snapshot(root_dir, options = {})
|
55
|
+
repo = options[:repo] || Percy.config.repo
|
56
|
+
strip_prefix = File.absolute_path(options[:strip_prefix] || root_dir)
|
57
|
+
autoload_remote_resources = options[:autoload_remote_resources] || false
|
58
|
+
|
59
|
+
# Create a Percy build for the snapshots.
|
60
|
+
build = Percy.create_build(repo)
|
61
|
+
|
62
|
+
# Find all the static files in the given root directory.
|
63
|
+
root_paths = find_root_paths(root_dir, snapshots_regex: options[:snapshots_regex])
|
64
|
+
resource_paths = find_resource_paths(root_dir)
|
65
|
+
root_resources = build_resources(root_paths, strip_prefix, is_root: true)
|
66
|
+
related_resources = build_resources(resource_paths, strip_prefix)
|
67
|
+
|
68
|
+
if autoload_remote_resources
|
69
|
+
remote_urls = find_remote_urls(root_paths + resource_paths)
|
70
|
+
related_resources += build_remote_resources(remote_urls)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Upload a snapshot for every root resource, and associate the related_resources.
|
74
|
+
root_resources.each_with_index do |root_resource, i|
|
75
|
+
say "Uploading snapshot (#{i+1}/#{root_resources.length}): #{root_resource.resource_url}"
|
76
|
+
upload_snapshot(build, root_resource, related_resources)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Finalize the build.
|
80
|
+
Percy.finalize_build(build['data']['id'])
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def find_root_paths(dir_path, options = {})
|
86
|
+
snapshots_regex = options[:snapshots_regex] || DEFAULT_SNAPSHOTS_REGEX
|
87
|
+
|
88
|
+
file_paths = []
|
89
|
+
Find.find(dir_path).each do |relative_path|
|
90
|
+
path = File.absolute_path(relative_path)
|
91
|
+
# Skip directories.
|
92
|
+
next if !FileTest.file?(path)
|
93
|
+
# Skip files that don't match the snapshots_regex.
|
94
|
+
next if !path.match(snapshots_regex)
|
95
|
+
file_paths << path
|
96
|
+
end
|
97
|
+
file_paths
|
98
|
+
end
|
99
|
+
|
100
|
+
def find_resource_paths(dir_path)
|
101
|
+
file_paths = []
|
102
|
+
Find.find(dir_path).each do |relative_path|
|
103
|
+
path = File.absolute_path(relative_path)
|
104
|
+
|
105
|
+
# Skip directories.
|
106
|
+
next if !FileTest.file?(path)
|
107
|
+
# Skip dot files.
|
108
|
+
next if path.match(/\/\./)
|
109
|
+
# Only include files with the above static extensions.
|
110
|
+
next if !Percy::Cli::STATIC_RESOURCE_EXTENSIONS.include?(File.extname(path))
|
111
|
+
|
112
|
+
file_paths << path
|
113
|
+
end
|
114
|
+
file_paths
|
115
|
+
end
|
116
|
+
|
117
|
+
def find_remote_urls(file_paths)
|
118
|
+
urls = []
|
119
|
+
file_paths.each do |path|
|
120
|
+
extension = File.extname(path)
|
121
|
+
case extension
|
122
|
+
when '.html'
|
123
|
+
content = File.read(path)
|
124
|
+
urls += content.scan(HTML_REMOTE_URL_REGEX).map { |match| maybe_add_protocol(match[0]) }
|
125
|
+
when '.css'
|
126
|
+
content = File.read(path)
|
127
|
+
urls += content.scan(CSS_REMOTE_URL_REGEX).map { |match| maybe_add_protocol(match[0]) }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
urls.uniq
|
131
|
+
end
|
132
|
+
|
133
|
+
def maybe_add_protocol(url)
|
134
|
+
url[0..1] == '//' ? "http:#{url}" : url
|
135
|
+
end
|
136
|
+
|
137
|
+
def build_resources(paths, strip_prefix, options = {})
|
138
|
+
resources = []
|
139
|
+
|
140
|
+
# Strip trailing slash from strip_prefix.
|
141
|
+
strip_prefix = strip_prefix[0..-2] if strip_prefix[-1] == '/'
|
142
|
+
|
143
|
+
paths.each do |path|
|
144
|
+
sha = Digest::SHA256.hexdigest(File.read(path))
|
145
|
+
resource_url = URI.escape(path.sub(strip_prefix, ''))
|
146
|
+
resources << Percy::Client::Resource.new(
|
147
|
+
resource_url, sha: sha, is_root: options[:is_root], path: path)
|
148
|
+
end
|
149
|
+
resources
|
150
|
+
end
|
151
|
+
|
152
|
+
def build_remote_resources(remote_urls)
|
153
|
+
resources = []
|
154
|
+
|
155
|
+
bar = Commander::UI::ProgressBar.new(
|
156
|
+
remote_urls.length,
|
157
|
+
title: 'Fetching remote resources...',
|
158
|
+
format: ':title |:progress_bar| :percent_complete% complete - :url',
|
159
|
+
width: 40,
|
160
|
+
complete_message: nil,
|
161
|
+
)
|
162
|
+
|
163
|
+
remote_urls.each do |url|
|
164
|
+
bar.increment url: url
|
165
|
+
begin
|
166
|
+
response = Faraday.get(url)
|
167
|
+
rescue Faraday::Error::ConnectionFailed => e
|
168
|
+
say_error e
|
169
|
+
next
|
170
|
+
end
|
171
|
+
if response.status != 200
|
172
|
+
say_error "Remote resource failed, skipping: #{url}"
|
173
|
+
next
|
174
|
+
end
|
175
|
+
|
176
|
+
sha = Digest::SHA256.hexdigest(response.body)
|
177
|
+
resources << Percy::Client::Resource.new(url, sha: sha, content: response.body)
|
178
|
+
end
|
179
|
+
resources
|
180
|
+
end
|
181
|
+
|
182
|
+
def upload_snapshot(build, root_resource, related_resources)
|
183
|
+
all_resources = [root_resource] + related_resources
|
184
|
+
|
185
|
+
# Create the snapshot for this page. For simplicity, include all non-HTML resources in the
|
186
|
+
# snapshot as related resources. May seem inefficient, but they will only be uploaded once.
|
187
|
+
snapshot = Percy.create_snapshot(build['data']['id'], all_resources)
|
188
|
+
|
189
|
+
# Upload the content for any missing resources.
|
190
|
+
missing_resources = snapshot['data']['relationships']['missing-resources']['data']
|
191
|
+
bar = Commander::UI::ProgressBar.new(
|
192
|
+
missing_resources.length,
|
193
|
+
title: 'Uploading resources...',
|
194
|
+
format: ':title |:progress_bar| :percent_complete% complete - :resource_url',
|
195
|
+
width: 40,
|
196
|
+
complete_message: nil,
|
197
|
+
)
|
198
|
+
missing_resources.each do |missing_resource|
|
199
|
+
missing_resource_sha = missing_resource['id']
|
200
|
+
resource = all_resources.find { |r| r.sha == missing_resource_sha }
|
201
|
+
path = resource.resource_url
|
202
|
+
bar.increment resource_url: resource.resource_url
|
203
|
+
|
204
|
+
# Remote resources are stored in 'content', local resources are read from the filesystem.
|
205
|
+
content = resource.content || File.read("#{resource.path}")
|
206
|
+
|
207
|
+
Percy.upload_resource(build['data']['id'], content)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
data/lib/percy/cli/version.rb
CHANGED
data/lib/percy/cli.rb
CHANGED
@@ -1,6 +1,63 @@
|
|
1
|
-
require
|
1
|
+
require 'commander'
|
2
|
+
require 'percy'
|
3
|
+
require 'percy/cli/version'
|
4
|
+
require 'percy/cli/snapshot'
|
2
5
|
|
3
6
|
module Percy
|
4
|
-
|
7
|
+
class Cli
|
8
|
+
include Commander::Methods
|
9
|
+
include Percy::Cli::Snapshot
|
10
|
+
|
11
|
+
def say(*args)
|
12
|
+
$terminal.say(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def say_error(*args)
|
16
|
+
STDERR.puts *args
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
program :name, 'Percy CLI'
|
21
|
+
program :version, Percy::Cli::VERSION
|
22
|
+
program :description, 'Command-line interface for Percy (https://percy.io).'
|
23
|
+
program :help_formatter, :compact
|
24
|
+
default_command :help
|
25
|
+
|
26
|
+
command :snapshot do |c|
|
27
|
+
c.syntax = 'snapshot <root_dir>'
|
28
|
+
c.description = 'Snapshot a folder of static files.'
|
29
|
+
c.option \
|
30
|
+
'--strip_prefix PATH',
|
31
|
+
String,
|
32
|
+
'Directory path to strip from generated URLs. Defaults to the given root directory.'
|
33
|
+
c.option \
|
34
|
+
'--repo STRING',
|
35
|
+
String,
|
36
|
+
'Full GitHub repo slug (owner/repo-name). Defaults to the local git repo origin URL.'
|
37
|
+
c.option \
|
38
|
+
'--snapshots_regex REGEX',
|
39
|
+
String,
|
40
|
+
'Regular expression for matching the files to snapshot. Defaults to: "\.(html|htm)$"'
|
41
|
+
c.option \
|
42
|
+
'--autoload_remote_resources',
|
43
|
+
'Attempts to parse HTML and CSS for remote resources, fetch them, and include in ' +
|
44
|
+
'snapshots. This can be very useful if your static website relies on remote resources.'
|
45
|
+
|
46
|
+
c.action do |args, options|
|
47
|
+
options.default autoload_remote_resources: false
|
48
|
+
raise OptionParser::MissingArgument, 'root folder path is required' if args.empty?
|
49
|
+
if args.length > 1
|
50
|
+
raise OptionParser::MissingArgument, 'only a single root folder path can be given'
|
51
|
+
end
|
52
|
+
root_dir = args.first
|
53
|
+
|
54
|
+
run_snapshot(root_dir, options.__hash__)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
run!
|
59
|
+
end
|
5
60
|
end
|
6
61
|
end
|
62
|
+
|
63
|
+
|
data/percy-cli.gemspec
CHANGED
@@ -18,8 +18,12 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
+
spec.add_dependency 'commander', '~> 4'
|
21
22
|
spec.add_dependency 'percy-client', '~> 0.2'
|
23
|
+
spec.add_dependency 'faraday', '>= 0.8'
|
22
24
|
|
23
25
|
spec.add_development_dependency 'bundler', '~> 1.7'
|
24
26
|
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3'
|
28
|
+
spec.add_development_dependency 'webmock', '~> 1'
|
25
29
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
RSpec.describe Percy::Cli::Snapshot do
|
4
|
+
let(:root_dir) { File.expand_path('../testdata/', __FILE__) }
|
5
|
+
|
6
|
+
describe '#run_snapshot' do
|
7
|
+
xit 'snapshots a root directory of static files' do
|
8
|
+
# TODO(fotinakis): tests for this.
|
9
|
+
end
|
10
|
+
end
|
11
|
+
describe '#find_root_paths' do
|
12
|
+
it 'returns only the HTML files in the directory' do
|
13
|
+
paths = Percy::Cli.new.send(:find_root_paths, root_dir)
|
14
|
+
expect(paths).to match_array([
|
15
|
+
File.join(root_dir, 'index.html'),
|
16
|
+
File.join(root_dir, 'subdir/test.html'),
|
17
|
+
])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
describe '#find_resource_paths' do
|
21
|
+
it 'returns only the related static files in the directory' do
|
22
|
+
paths = Percy::Cli.new.send(:find_resource_paths, root_dir)
|
23
|
+
expect(paths).to match_array([
|
24
|
+
File.join(root_dir, 'css/base.css'),
|
25
|
+
File.join(root_dir, 'css/test with spaces.css'),
|
26
|
+
File.join(root_dir, 'images/jellybeans.png'),
|
27
|
+
])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
describe '#find_remote_urls' do
|
31
|
+
it 'returns remote resources referenced throughout the static website' do
|
32
|
+
root_paths = Percy::Cli.new.send(:find_root_paths, root_dir)
|
33
|
+
resource_paths = Percy::Cli.new.send(:find_resource_paths, root_dir)
|
34
|
+
|
35
|
+
remote_urls = Percy::Cli.new.send(:find_remote_urls, root_paths + resource_paths)
|
36
|
+
expect(remote_urls).to match_array([
|
37
|
+
# In index.html:
|
38
|
+
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css',
|
39
|
+
'http://example.com:12345/test-no-protocol.css',
|
40
|
+
'http://example.com:12345/test-duplicate.css',
|
41
|
+
'http://example.com:12345/test-query-param.css?v=1',
|
42
|
+
'http://example.com:12345/test-single-quotes.css',
|
43
|
+
'http://example.com:12345/test-diff-tag-order.css',
|
44
|
+
|
45
|
+
# In base.css:
|
46
|
+
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css',
|
47
|
+
])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
describe '#build_resources' do
|
51
|
+
it 'returns resource objects' do
|
52
|
+
paths = [File.join(root_dir, 'css/base.css')]
|
53
|
+
resources = Percy::Cli.new.send(:build_resources, paths, root_dir)
|
54
|
+
|
55
|
+
expect(resources.length).to eq(1)
|
56
|
+
expect(resources.first.sha).to eq(Digest::SHA256.hexdigest(File.read(paths.first)))
|
57
|
+
expect(resources.first.is_root).to be_nil
|
58
|
+
expect(resources.first.content).to be_nil
|
59
|
+
expect(resources.first.path).to eq(paths.first)
|
60
|
+
end
|
61
|
+
it 'returns resource objects with is_root set if given' do
|
62
|
+
paths = [File.join(root_dir, 'index.html')]
|
63
|
+
resources = Percy::Cli.new.send(:build_resources, paths, root_dir, is_root: true)
|
64
|
+
|
65
|
+
expect(resources.length).to eq(1)
|
66
|
+
expect(resources.first.resource_url).to eq('/index.html')
|
67
|
+
expect(resources.first.sha).to eq(Digest::SHA256.hexdigest(File.read(paths.first)))
|
68
|
+
expect(resources.first.is_root).to be_truthy
|
69
|
+
expect(resources.first.content).to be_nil
|
70
|
+
expect(resources.first.path).to eq(paths.first)
|
71
|
+
end
|
72
|
+
it 'encodes the resource_url' do
|
73
|
+
paths = [File.join(root_dir, 'css/test with spaces.css')]
|
74
|
+
resources = Percy::Cli.new.send(:build_resources, paths, root_dir)
|
75
|
+
|
76
|
+
expect(resources.length).to eq(1)
|
77
|
+
expect(resources.first.resource_url).to eq('/css/test%20with%20spaces.css')
|
78
|
+
expect(resources.first.sha).to eq(Digest::SHA256.hexdigest(File.read(paths.first)))
|
79
|
+
expect(resources.first.is_root).to be_nil
|
80
|
+
expect(resources.first.content).to be_nil
|
81
|
+
expect(resources.first.path).to eq(paths.first)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
describe '#build_remote_resources' do
|
85
|
+
it 'fetches the remote URLs and creates resource objects' do
|
86
|
+
urls = [
|
87
|
+
'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css',
|
88
|
+
'http://example.com:12345/test-failure.css',
|
89
|
+
]
|
90
|
+
stub_request(:get, 'http://example.com:12345/test-failure.css').to_return(status: 400)
|
91
|
+
|
92
|
+
resources = Percy::Cli.new.send(:build_remote_resources, urls)
|
93
|
+
|
94
|
+
expect(resources.length).to eq(1)
|
95
|
+
expect(resources[0].resource_url).to eq(urls[0])
|
96
|
+
expect(resources[0].sha).to be
|
97
|
+
expect(resources[0].is_root).to be_nil
|
98
|
+
expect(resources[0].content).to be
|
99
|
+
expect(resources[0].path).to be_nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
describe '#upload_snapshot' do
|
103
|
+
xit 'uploads the given resources to the build' do
|
104
|
+
# TODO(fotinakis): tests for this.
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
h1 { color: blue; }
|
File without changes
|
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<title>Test Percy CLI</title>
|
4
|
+
<link href="css/base.css" rel="stylesheet" type="text/css">
|
5
|
+
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" type="text/css">
|
6
|
+
<link href="//example.com:12345/test-no-protocol.css" rel="stylesheet" type="text/css">
|
7
|
+
<link href='http://example.com:12345/test-single-quotes.css' rel="stylesheet" type="text/css">
|
8
|
+
<link href="http://example.com:12345/test-query-param.css?v=1" rel="stylesheet" type="text/css">
|
9
|
+
|
10
|
+
<link href="http://example.com:12345/test-duplicate.css" rel="stylesheet" type="text/css">
|
11
|
+
<link href="http://example.com:12345/test-duplicate.css" rel="stylesheet" type="text/css">
|
12
|
+
|
13
|
+
<link rel="stylesheet" type="text/css" href="http://example.com:12345/test-diff-tag-order.css">
|
14
|
+
|
15
|
+
<h1>Hello World!</h1>
|
16
|
+
|
17
|
+
Just some text, should not be included:
|
18
|
+
http://example.com/should-not-be-included.css
|
19
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<!DOCTYPE html><html>Hello World!</html>
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'percy/cli'
|
2
|
+
require 'webmock/rspec'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.expect_with :rspec do |expectations|
|
6
|
+
# This option will default to `true` in RSpec 4.
|
7
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
8
|
+
end
|
9
|
+
|
10
|
+
config.mock_with :rspec do |mocks|
|
11
|
+
mocks.verify_partial_doubles = true
|
12
|
+
end
|
13
|
+
|
14
|
+
config.disable_monkey_patching!
|
15
|
+
|
16
|
+
# Run specs in random order to surface order dependencies. If you find an
|
17
|
+
# order dependency and want to debug it, you can fix the order by providing
|
18
|
+
# the seed, which is printed after each run.
|
19
|
+
# --seed 1234
|
20
|
+
config.order = :random
|
21
|
+
|
22
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
23
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
24
|
+
# test failures related to randomization by passing the same `--seed` value
|
25
|
+
# as the one that triggered the failure.
|
26
|
+
Kernel.srand config.seed
|
27
|
+
|
28
|
+
config.before(:each) do
|
29
|
+
WebMock.disable_net_connect!(allow: [
|
30
|
+
'maxcdn.bootstrapcdn.com',
|
31
|
+
'ajax.googleapis.com',
|
32
|
+
])
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: percy-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Perceptual Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: commander
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: percy-client
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +38,20 @@ dependencies:
|
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.8'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.8'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: bundler
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +80,34 @@ dependencies:
|
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
82
|
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1'
|
55
111
|
description: ''
|
56
112
|
email:
|
57
113
|
- team@percy.io
|
@@ -61,14 +117,25 @@ extensions: []
|
|
61
117
|
extra_rdoc_files: []
|
62
118
|
files:
|
63
119
|
- ".gitignore"
|
120
|
+
- ".rspec"
|
121
|
+
- ".travis.yml"
|
64
122
|
- Gemfile
|
65
123
|
- LICENSE
|
66
124
|
- README.md
|
67
125
|
- Rakefile
|
68
126
|
- bin/percy
|
69
127
|
- lib/percy/cli.rb
|
128
|
+
- lib/percy/cli/snapshot.rb
|
70
129
|
- lib/percy/cli/version.rb
|
71
130
|
- percy-cli.gemspec
|
131
|
+
- spec/percy/cli/snapshot_spec.rb
|
132
|
+
- spec/percy/cli/testdata/css/base.css
|
133
|
+
- spec/percy/cli/testdata/css/test with spaces.css
|
134
|
+
- spec/percy/cli/testdata/css/unrelated-no-extension
|
135
|
+
- spec/percy/cli/testdata/images/jellybeans.png
|
136
|
+
- spec/percy/cli/testdata/index.html
|
137
|
+
- spec/percy/cli/testdata/subdir/test.html
|
138
|
+
- spec/spec_helper.rb
|
72
139
|
homepage: ''
|
73
140
|
licenses:
|
74
141
|
- MIT
|
@@ -93,5 +160,13 @@ rubygems_version: 2.2.2
|
|
93
160
|
signing_key:
|
94
161
|
specification_version: 4
|
95
162
|
summary: Percy command-line interface
|
96
|
-
test_files:
|
163
|
+
test_files:
|
164
|
+
- spec/percy/cli/snapshot_spec.rb
|
165
|
+
- spec/percy/cli/testdata/css/base.css
|
166
|
+
- spec/percy/cli/testdata/css/test with spaces.css
|
167
|
+
- spec/percy/cli/testdata/css/unrelated-no-extension
|
168
|
+
- spec/percy/cli/testdata/images/jellybeans.png
|
169
|
+
- spec/percy/cli/testdata/index.html
|
170
|
+
- spec/percy/cli/testdata/subdir/test.html
|
171
|
+
- spec/spec_helper.rb
|
97
172
|
has_rdoc:
|