percy-cli 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|