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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b424e941cc250a7a550f938ae216a99c51400ec
4
- data.tar.gz: 5bf813f4abe4ced40d3b7f213801b33caa39d0ea
3
+ metadata.gz: a79b07a50003692a4126836dca74ca72787c479c
4
+ data.tar.gz: 44b4607a5fe3267aae10e772c7b7057f33ded2eb
5
5
  SHA512:
6
- metadata.gz: a2e75cec943b3e4919590d256e562f129350a1a0775c34ea3de40e206e9300b105d2091b70f56b3a8a2baec0712222d47d3e2b2b20f5526058c41ee5251e6751
7
- data.tar.gz: db17492803a3c36a5a34c30f033590f54f4305137adf3155ec212051b2931a8097564984642ee387db2c22cc7fc01593833e7623b803e0ee8e631a27bdf8a24a
6
+ metadata.gz: 29b2632be605f99a12265a798b7afb40552934bc7445f514a48723ed9842d84672d1524a2f7f1f32fdc1f2615043ed96d14bdb526c3165961a03a0e5590a4549
7
+ data.tar.gz: 14b7f5941ca563a9bf5c3df841638a162d5c16dd3e3ede57fc644e9fe1190d39ba63dc6e10893f6e6a1e3a644c387e6f652a0bad0f57b0a1035b0b829cd57639
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format d
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.1.1
5
+ - 2.2.2
6
+ - ruby-head
7
+ script: bundle exec rspec
data/bin/percy CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'commander'
3
4
  require 'percy/cli'
4
5
 
5
- puts 'test'
6
+ Percy::Cli.new.run if $0 == __FILE__
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Percy
2
- module Cli
3
- VERSION = "0.0.1"
2
+ class Cli
3
+ VERSION = '0.0.2'
4
4
  end
5
5
  end
data/lib/percy/cli.rb CHANGED
@@ -1,6 +1,63 @@
1
- require "percy/cli/version"
1
+ require 'commander'
2
+ require 'percy'
3
+ require 'percy/cli/version'
4
+ require 'percy/cli/snapshot'
2
5
 
3
6
  module Percy
4
- module Cli
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,4 @@
1
+ @import url( //ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css);
2
+ @import url('/local/not-included.css');
3
+
4
+ h1 { color: red; }
@@ -0,0 +1 @@
1
+ h1 { color: blue; }
@@ -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>
@@ -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.1
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-04 00:00:00.000000000 Z
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: