percy-capybara 3.2.0 → 4.0.0.pre.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +39 -0
  3. data/.gitignore +1 -0
  4. data/DEVELOPING.md +26 -0
  5. data/README.md +2 -2
  6. data/lib/environment.rb +31 -0
  7. data/lib/percy.rb +119 -0
  8. data/lib/version.rb +3 -0
  9. data/package-lock.json +2155 -0
  10. data/package.json +6 -0
  11. data/percy-capybara.gemspec +3 -12
  12. data/spec/lib/percy/environment_spec.rb +31 -0
  13. data/spec/lib/percy/percy_spec.rb +55 -0
  14. data/spec/spec_helper.rb +4 -44
  15. metadata +17 -233
  16. data/.travis.yml +0 -17
  17. data/lib/percy/capybara.rb +0 -60
  18. data/lib/percy/capybara/anywhere.rb +0 -37
  19. data/lib/percy/capybara/client.rb +0 -127
  20. data/lib/percy/capybara/client/builds.rb +0 -81
  21. data/lib/percy/capybara/client/snapshots.rb +0 -66
  22. data/lib/percy/capybara/client/user_agent.rb +0 -37
  23. data/lib/percy/capybara/httpfetcher.rb +0 -36
  24. data/lib/percy/capybara/loaders/base_loader.rb +0 -161
  25. data/lib/percy/capybara/loaders/ember_cli_rails_loader.rb +0 -52
  26. data/lib/percy/capybara/loaders/filesystem_loader.rb +0 -37
  27. data/lib/percy/capybara/loaders/native_loader.rb +0 -287
  28. data/lib/percy/capybara/loaders/sprockets_loader.rb +0 -99
  29. data/lib/percy/capybara/rspec.rb +0 -8
  30. data/lib/percy/capybara/version.rb +0 -5
  31. data/spec/lib/percy/capybara/client/builds_spec.rb +0 -171
  32. data/spec/lib/percy/capybara/client/ember_test_data/ember-cli/admin/assets/percy-admin.svg +0 -34
  33. data/spec/lib/percy/capybara/client/ember_test_data/ember-cli/admin/index.html +0 -1
  34. data/spec/lib/percy/capybara/client/ember_test_data/ember-cli/admin/percy-admin-public.svg +0 -34
  35. data/spec/lib/percy/capybara/client/ember_test_data/ember-cli/frontend/assets/percy-frontend.svg +0 -34
  36. data/spec/lib/percy/capybara/client/ember_test_data/ember-cli/frontend/index.html +0 -1
  37. data/spec/lib/percy/capybara/client/ember_test_data/ember-cli/frontend/percy-frontend-public.svg +0 -34
  38. data/spec/lib/percy/capybara/client/rails_public_test_data/large-file-skipped.png +0 -0
  39. data/spec/lib/percy/capybara/client/rails_public_test_data/percy-from-public.svg +0 -34
  40. data/spec/lib/percy/capybara/client/rails_public_test_data/symlink_to_images +0 -1
  41. data/spec/lib/percy/capybara/client/snapshots_spec.rb +0 -97
  42. data/spec/lib/percy/capybara/client/symlink_test_data/test.png +0 -0
  43. data/spec/lib/percy/capybara/client/test_data/assets/css/digested-f3420c6aee71c137a3ca39727052811bae84b2f37d898f4db242e20656a1579e.css +0 -1
  44. data/spec/lib/percy/capybara/client/test_data/assets/images/large-file-skipped.png +0 -0
  45. data/spec/lib/percy/capybara/client/test_data/css/base.css +0 -1
  46. data/spec/lib/percy/capybara/client/test_data/css/digested.css +0 -1
  47. data/spec/lib/percy/capybara/client/test_data/css/font.css +0 -8
  48. data/spec/lib/percy/capybara/client/test_data/css/imports.css +0 -1
  49. data/spec/lib/percy/capybara/client/test_data/css/level0-imports.css +0 -2
  50. data/spec/lib/percy/capybara/client/test_data/css/level1-imports.css +0 -2
  51. data/spec/lib/percy/capybara/client/test_data/css/level2-imports.css +0 -1
  52. data/spec/lib/percy/capybara/client/test_data/css/simple-imports.css +0 -1
  53. data/spec/lib/percy/capybara/client/test_data/css/source.css.map +0 -2
  54. data/spec/lib/percy/capybara/client/test_data/iframe.html +0 -7
  55. data/spec/lib/percy/capybara/client/test_data/images/bg-relative-to-root.png +0 -0
  56. data/spec/lib/percy/capybara/client/test_data/images/bg-relative.png +0 -0
  57. data/spec/lib/percy/capybara/client/test_data/images/bg-stacked.png +0 -0
  58. data/spec/lib/percy/capybara/client/test_data/images/img-relative-to-root.png +0 -0
  59. data/spec/lib/percy/capybara/client/test_data/images/img-relative.png +0 -0
  60. data/spec/lib/percy/capybara/client/test_data/images/percy.svg +0 -34
  61. data/spec/lib/percy/capybara/client/test_data/images/srcset-base.png +0 -0
  62. data/spec/lib/percy/capybara/client/test_data/images/srcset-first.png +0 -0
  63. data/spec/lib/percy/capybara/client/test_data/images/srcset-second.png +0 -0
  64. data/spec/lib/percy/capybara/client/test_data/index.html +0 -1
  65. data/spec/lib/percy/capybara/client/test_data/js/base.js +0 -1
  66. data/spec/lib/percy/capybara/client/test_data/test-css.html +0 -20
  67. data/spec/lib/percy/capybara/client/test_data/test-font.html +0 -9
  68. data/spec/lib/percy/capybara/client/test_data/test-iframe.html +0 -8
  69. data/spec/lib/percy/capybara/client/test_data/test-images.html +0 -51
  70. data/spec/lib/percy/capybara/client/test_data/test-localtest-me-images.html +0 -8
  71. data/spec/lib/percy/capybara/client/user_agent_spec.rb +0 -45
  72. data/spec/lib/percy/capybara/client_spec.rb +0 -232
  73. data/spec/lib/percy/capybara/http_fetcher_spec.rb +0 -17
  74. data/spec/lib/percy/capybara/loaders/base_loader_spec.rb +0 -122
  75. data/spec/lib/percy/capybara/loaders/ember_cli_rails_loader_spec.rb +0 -86
  76. data/spec/lib/percy/capybara/loaders/filesystem_loader_spec.rb +0 -166
  77. data/spec/lib/percy/capybara/loaders/native_loader_spec.rb +0 -300
  78. data/spec/lib/percy/capybara/loaders/sprockets_loader_spec.rb +0 -119
  79. data/spec/lib/percy/capybara_spec.rb +0 -101
  80. data/spec/support/test_helpers.rb +0 -60
@@ -1,17 +0,0 @@
1
- RSpec.describe Percy::Capybara::HttpFetcher do
2
- it 'takes a URL and returns a response' do
3
- response = Percy::Capybara::HttpFetcher.fetch('https://i.imgur.com/Umkjdao.png')
4
-
5
- # Slightly magical hash, just a SHA-256 sum of the image above.
6
- expect(Digest::SHA256.hexdigest(response.body)).to eq(
7
- '4beb51550bef8e9e30d37ea8c13658e99bb01722062f218185e419af5ad93e13',
8
- )
9
- expect(response.content_type).to eq('image/png')
10
- end
11
- it 'returns nil if fetch failed' do
12
- expect(Percy::Capybara::HttpFetcher.fetch('http://i.imgur.com/fake-image.png')).to be_nil
13
- expect(Percy::Capybara::HttpFetcher.fetch('http://i.imgur.com/fake image.png')).to be_nil
14
- # FIXME.
15
- # expect(Percy::Capybara::HttpFetcher.fetch('bad-url')).to be_nil
16
- end
17
- end
@@ -1,122 +0,0 @@
1
- IFRAME_PATH = File.expand_path('../../client/test_data/test-iframe.html', __FILE__)
2
-
3
- class RackAppWithIframe
4
- def self.call(_env)
5
- [200, {}, File.read(IFRAME_PATH)]
6
- end
7
- end
8
-
9
- RSpec.describe Percy::Capybara::Loaders::BaseLoader do
10
- let(:loader) { Percy::Capybara::Loaders::BaseLoader.new }
11
-
12
- describe '#root_html_resource', type: :feature, js: true do
13
- it 'includes the root DOM HTML' do
14
- visit '/'
15
-
16
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page)
17
- resource = loader.root_html_resource
18
-
19
- expect(resource.is_root).to be_truthy
20
- expect(resource.mimetype).to eq('text/html')
21
- expect(resource.resource_url).to match('/')
22
- expect(resource.content).to include('Hello World!')
23
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
24
- end
25
- end
26
- describe '#iframes_resources', type: :feature, js: true do
27
- it 'excludes the iframe by default' do
28
- visit '/test-iframe.html'
29
-
30
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page)
31
- resources = loader.iframes_resources
32
- expect(resources).to eq([])
33
- end
34
-
35
- it 'includes the iframe with DOM HTML when include_iframes true' do
36
- visit '/test-iframe.html'
37
-
38
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page, include_iframes: true)
39
- resources = loader.iframes_resources
40
-
41
- expect(resources.size).to eq(1) # doesn't include iframe to remote host
42
- last_resource = resources.last
43
- expect(last_resource.resource_url).to eq('/iframe.html')
44
- expect(last_resource.mimetype).to eq('text/html')
45
- expect(last_resource.content).to include('Inside iframe')
46
- end
47
- it 'skips poltergeist frame not found errors when include_iframes true' do
48
- visit '/test-iframe.html'
49
-
50
- expect(page).to receive(:within_frame).twice
51
- .and_raise(Capybara::Poltergeist::FrameNotFound, 'Hi')
52
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page, include_iframes: true)
53
- resources = loader.iframes_resources
54
- expect(resources.size).to eq(0)
55
- end
56
- it 'skips poltergeist timeout errors when include_iframes true' do
57
- visit '/test-iframe.html'
58
-
59
- expect(page).to receive(:within_frame).twice
60
- .and_raise(Capybara::Poltergeist::TimeoutError, 'Hi')
61
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page, include_iframes: true)
62
- resources = loader.iframes_resources
63
- expect(resources.size).to eq(0)
64
- end
65
- end
66
- describe '#build_resources' do
67
- it 'raises a NotImplementedError' do
68
- expect { loader.build_resources }.to raise_error(NotImplementedError)
69
- end
70
- end
71
- describe '#snapshot_resources' do
72
- it 'raises a NotImplementedError' do
73
- expect { loader.snapshot_resources }.to raise_error(NotImplementedError)
74
- end
75
- end
76
- describe '#current_path' do
77
- it 'returns the current path of the page, stripping the domain if it exists' do
78
- page_double = double('page')
79
-
80
- expect(page_double).to receive(:current_url).and_return('/')
81
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page_double)
82
- expect(loader.current_path).to eq('/')
83
-
84
- expect(page_double).to receive(:current_url).and_return('/test')
85
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page_double)
86
- expect(loader.current_path).to eq('/test')
87
-
88
- expect(page_double).to receive(:current_url).and_return('/test/a')
89
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page_double)
90
- expect(loader.current_path).to eq('/test/a')
91
-
92
- # Rack::Test returns a full example.com URL, so we want to make sure it is stripped:
93
- expect(page_double).to receive(:current_url).and_return('http://www.example.com/')
94
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page_double)
95
- expect(loader.current_path).to eq('/')
96
-
97
- expect(page_double).to receive(:current_url).and_return('about:srcdoc')
98
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page_double)
99
- expect(loader.current_path).to eq('/about:srcdoc')
100
- end
101
- end
102
-
103
- context 'Rack::Test', type: :feature do
104
- before(:each) { Capybara.app = RackAppWithIframe }
105
- after(:each) { Capybara.app = nil }
106
-
107
- describe '#iframes_resources' do
108
- it 'is silently ignored' do
109
- visit '/test-iframe.html'
110
- loader = Percy::Capybara::Loaders::BaseLoader.new(page: page)
111
- expect(loader.iframes_resources).to eq([])
112
- end
113
- end
114
- end
115
-
116
- describe '#_uri_join' do
117
- it 'joins files into a uri' do
118
- expect(Percy::Capybara::Loaders::BaseLoader.new.send(:_uri_join, 'foo/', '/bar', 'baz'))
119
- .to eq('foo/bar/baz')
120
- end
121
- end
122
- end
@@ -1,86 +0,0 @@
1
- require 'set'
2
-
3
- RSpec.describe Percy::Capybara::Loaders::EmberCliRailsLoader do
4
- let(:assets_dir) { File.expand_path('../../client/ember_test_data', __FILE__) }
5
- let(:mounted_apps) { {frontend: ''} }
6
- let(:digest_enabled) { false }
7
-
8
- let(:environment) do
9
- environment = Sprockets::Environment.new(assets_dir)
10
- environment.append_path '.'
11
- environment
12
- end
13
-
14
- let(:loader) do
15
- Percy::Capybara::Loaders::EmberCliRailsLoader.new(
16
- mounted_apps,
17
- sprockets_environment: environment,
18
- sprockets_options: sprockets_options,
19
- )
20
- end
21
-
22
- let(:sprockets_options) do
23
- options = instance_double('options')
24
- # Set specific files we want to compile. In normal use, this would be all asset files.
25
- # For this test we just use .svg files
26
- precompile_list = [/(?:\/|\\|\A)\.svg/]
27
- allow(options).to receive(:precompile).and_return(precompile_list)
28
- allow(options).to receive(:digest).and_return(digest_enabled)
29
- options
30
- end
31
-
32
- describe 'initialize' do
33
- context 'all args supplied' do
34
- it 'successfully initializes' do
35
- expect { loader }.to_not raise_error
36
- end
37
- end
38
-
39
- context 'mounted_apps not specified' do
40
- let(:mounted_apps) { nil }
41
-
42
- it 'raises an error' do
43
- expect { loader }.to raise_error(StandardError)
44
- end
45
- end
46
- end
47
-
48
- describe '#build_resources' do
49
- shared_examples 'a mounted ember app' do |mounted_apps|
50
- ember_app = mounted_apps.keys.first
51
- mount_path = mounted_apps.values.first
52
-
53
- let(:ember_app) { ember_app }
54
- let(:mount_path) { mounted_apps.values.first }
55
- let(:dist_dir) { File.join(assets_dir, 'ember-cli', ember_app.to_s) }
56
- let(:loader) do
57
- Percy::Capybara::Loaders::EmberCliRailsLoader.new(
58
- mounted_apps,
59
- sprockets_environment: environment,
60
- sprockets_options: sprockets_options,
61
- )
62
- end
63
-
64
- context "called '#{ember_app}' and mounted at '#{mount_path}'" do
65
- before(:each) do
66
- allow(loader).to receive(:_dist_path_for_app).and_return(dist_dir)
67
- end
68
-
69
- it 'builds the expected resources' do
70
- built_urls = Set.new(loader.build_resources.collect(&:resource_url))
71
-
72
- expected_urls = Set.new
73
- expected_urls << loader._uri_join(mount_path, "/assets/percy-#{ember_app}.svg")
74
- expected_urls << loader._uri_join(mount_path, "/percy-#{ember_app}-public.svg")
75
-
76
- expect(expected_urls.subset?(built_urls)).to be true
77
- end
78
- end
79
- end
80
-
81
- it_behaves_like 'a mounted ember app', frontend: '/'
82
- it_behaves_like 'a mounted ember app', frontend: ''
83
- it_behaves_like 'a mounted ember app', admin: '/admin'
84
- it_behaves_like 'a mounted ember app', admin: '/admin/'
85
- end
86
- end
@@ -1,166 +0,0 @@
1
- RSpec.describe Percy::Capybara::Loaders::FilesystemLoader do
2
- let(:fake_page) { OpenStruct.new(current_url: 'http://localhost/foo') }
3
- let(:assets_dir) { File.expand_path('../../client/test_data', __FILE__) }
4
- let(:base_url) { '/url-prefix/' }
5
- let(:loader) do
6
- Percy::Capybara::Loaders::FilesystemLoader.new(
7
- base_url: base_url,
8
- assets_dir: assets_dir,
9
- page: fake_page,
10
- )
11
- end
12
-
13
- describe 'initialize' do
14
- context 'assets_dir not specified' do
15
- let(:assets_dir) { nil }
16
-
17
- it 'raises an error' do
18
- expect { loader }.to raise_error(ArgumentError)
19
- end
20
- end
21
- context 'assets_dir is not an absolute path' do
22
- let(:assets_dir) { '../../client/test_data' }
23
-
24
- it 'raises an error' do
25
- expect { loader }.to raise_error(ArgumentError)
26
- end
27
- end
28
- context "assets_dir doesn't exist" do
29
- let(:assets_dir) { File.expand_path('../../client/test-data-doesnt-exist', __FILE__) }
30
-
31
- it 'raises an error' do
32
- expect { loader }.to raise_error(ArgumentError)
33
- end
34
- end
35
- end
36
-
37
- describe '#snapshot_resources', type: :feature, js: true do
38
- it 'returns the root HTML' do
39
- visit '/'
40
- loader = Percy::Capybara::Loaders::FilesystemLoader.new(
41
- base_url: base_url,
42
- assets_dir: assets_dir,
43
- page: page,
44
- )
45
- expect(loader.snapshot_resources.collect(&:resource_url)).to match_array(['/'])
46
- end
47
- it 'returns the visited html resource' do
48
- visit '/test-css.html'
49
- loader = Percy::Capybara::Loaders::FilesystemLoader.new(
50
- base_url: base_url,
51
- assets_dir: assets_dir,
52
- page: page,
53
- )
54
- resource_urls = loader.snapshot_resources.collect(&:resource_url)
55
- expect(resource_urls).to match_array(['/test-css.html'])
56
- end
57
- end
58
-
59
- describe '#build_resources' do
60
- context 'assets_dir including all test files' do
61
- it 'returns all included assets as resources' do
62
- actual_paths = loader.build_resources.collect do |resource|
63
- resource.path.gsub(assets_dir, '')
64
- end
65
- expected_paths = [
66
- '/assets/css/digested-f3420c6aee71c137a3ca39727052811ba' \
67
- 'e84b2f37d898f4db242e20656a1579e.css',
68
- '/css/base.css',
69
- '/css/font.css',
70
- '/css/digested.css',
71
- '/css/imports.css',
72
- '/css/level0-imports.css',
73
- '/css/level1-imports.css',
74
- '/css/level2-imports.css',
75
- '/css/simple-imports.css',
76
- '/iframe.html',
77
- '/images/bg-relative-to-root.png',
78
- '/images/bg-relative.png',
79
- '/images/bg-stacked.png',
80
- '/images/img-relative-to-root.png',
81
- '/images/img-relative.png',
82
- '/images/percy.svg',
83
- '/images/srcset-base.png',
84
- '/images/srcset-first.png',
85
- '/images/srcset-second.png',
86
- '/index.html',
87
- '/js/base.js',
88
- '/test-css.html',
89
- '/test-font.html',
90
- '/test-iframe.html',
91
- '/test-images.html',
92
- '/test-localtest-me-images.html',
93
- ]
94
- expect(actual_paths).to match_array(expected_paths)
95
-
96
- expected_urls = loader.build_resources.collect(&:resource_url)
97
- actual_urls = [
98
- '/url-prefix/assets/css/digested-f3420c6aee71c137a3ca' \
99
- '39727052811bae84b2f37d898f4db242e20656a1579e.css',
100
- '/url-prefix/css/base.css',
101
- '/url-prefix/css/digested.css',
102
- '/url-prefix/css/imports.css',
103
- '/url-prefix/css/level0-imports.css',
104
- '/url-prefix/css/level1-imports.css',
105
- '/url-prefix/css/level2-imports.css',
106
- '/url-prefix/css/simple-imports.css',
107
- '/url-prefix/css/font.css',
108
- '/url-prefix/iframe.html',
109
- '/url-prefix/images/bg-relative-to-root.png',
110
- '/url-prefix/images/bg-relative.png',
111
- '/url-prefix/images/bg-stacked.png',
112
- '/url-prefix/images/img-relative-to-root.png',
113
- '/url-prefix/images/img-relative.png',
114
- '/url-prefix/images/percy.svg',
115
- '/url-prefix/images/srcset-base.png',
116
- '/url-prefix/images/srcset-first.png',
117
- '/url-prefix/images/srcset-second.png',
118
- '/url-prefix/index.html',
119
- '/url-prefix/js/base.js',
120
- '/url-prefix/test-css.html',
121
- '/url-prefix/test-font.html',
122
- '/url-prefix/test-iframe.html',
123
- '/url-prefix/test-images.html',
124
- '/url-prefix/test-localtest-me-images.html',
125
- ]
126
- expect(actual_urls).to match_array(expected_urls)
127
- end
128
- it 'works with different base_url configs' do
129
- loader = Percy::Capybara::Loaders::FilesystemLoader.new(
130
- base_url: '/url-prefix/',
131
- assets_dir: assets_dir,
132
- )
133
- expected_urls = loader.build_resources.collect(&:resource_url)
134
- expect(expected_urls).to include('/url-prefix/css/font.css')
135
-
136
- loader = Percy::Capybara::Loaders::FilesystemLoader.new(
137
- base_url: '/url-prefix',
138
- assets_dir: assets_dir,
139
- )
140
- expected_urls = loader.build_resources.collect(&:resource_url)
141
- expect(expected_urls).to include('/url-prefix/css/font.css')
142
-
143
- loader = Percy::Capybara::Loaders::FilesystemLoader.new(
144
- base_url: '/',
145
- assets_dir: assets_dir,
146
- )
147
- expected_urls = loader.build_resources.collect(&:resource_url)
148
- expect(expected_urls).to include('/css/font.css')
149
-
150
- loader = Percy::Capybara::Loaders::FilesystemLoader.new(
151
- base_url: '',
152
- assets_dir: assets_dir,
153
- )
154
- expected_urls = loader.build_resources.collect(&:resource_url)
155
- expect(expected_urls).to include('/css/font.css')
156
- end
157
- end
158
- context 'assets_dir with only skippable resources' do
159
- let(:assets_dir) { File.expand_path('../../client/test_data/assets/images', __FILE__) }
160
-
161
- it 'returns an empty list' do
162
- expect(loader.build_resources).to eq([])
163
- end
164
- end
165
- end
166
- end
@@ -1,300 +0,0 @@
1
- RSpec.describe Percy::Capybara::Loaders::NativeLoader do
2
- let(:fake_page) { OpenStruct.new(current_url: 'http://localhost/foo') }
3
- let(:asset_hostnames) { nil }
4
- let(:loader) do
5
- Percy::Capybara::Loaders::NativeLoader.new(page: fake_page, asset_hostnames: asset_hostnames)
6
- end
7
-
8
- describe '#build_resources' do
9
- it 'returns an empty list' do
10
- expect(loader.build_resources).to eq([])
11
- end
12
- end
13
- describe '#snapshot_resources', type: :feature, js: true do
14
- it 'returns the root HTML' do
15
- visit '/'
16
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
17
- expect(loader.snapshot_resources.collect(&:resource_url)).to match_array(['/'])
18
- end
19
- it 'returns the root HTML and CSS resources' do
20
- visit '/test-css.html'
21
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
22
- resource_urls = loader.snapshot_resources.collect(&:resource_url)
23
- expect(resource_urls).to match_array(
24
- [
25
- '/test-css.html',
26
- '/css/base.css',
27
- '/css/imports.css',
28
- '/css/level0-imports.css',
29
- '/css/level1-imports.css',
30
- '/css/level2-imports.css',
31
- '/css/simple-imports.css',
32
- ],
33
- )
34
- end
35
- it 'returns the font resources' do
36
- visit '/test-font.html'
37
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
38
- resource_urls = loader.snapshot_resources.collect(&:resource_url)
39
- expect(resource_urls).to match_array(
40
- [
41
- '/test-font.html',
42
- '/css/font.css',
43
- '/assets/bootstrap/glyphicons-halflings-regular-13634da.eot',
44
- ],
45
- )
46
- end
47
- it 'returns the root HTML and image resources' do
48
- visit '/test-images.html'
49
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
50
- resource_urls = loader.snapshot_resources.collect(&:resource_url)
51
- expect(resource_urls).to match_array(
52
- [
53
- '/test-images.html',
54
- '/images/img-relative.png',
55
- '/images/img-relative-to-root.png',
56
- '/images/percy.svg',
57
- '/images/srcset-base.png',
58
- '/images/srcset-first.png',
59
- '/images/srcset-second.png',
60
- '/images/bg-relative.png',
61
- '/images/bg-relative-to-root.png',
62
- '/images/bg-stacked.png',
63
- ],
64
- )
65
- end
66
- end
67
- describe 'nonlocal.me', type: :feature, js: true do
68
- let(:orig_app_host) { Capybara.app_host }
69
-
70
- before(:each) do
71
- Capybara.app_host = Capybara.app_host.gsub('http://localhost:', 'http://localtest.me:')
72
- end
73
- after(:each) do
74
- Capybara.app_host = orig_app_host
75
- end
76
- it 'returns the root HTML and image resources' do
77
- visit '/test-localtest-me-images.html'
78
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
79
- resource_urls = loader.snapshot_resources.collect(&:resource_url)
80
- expect(resource_urls).to eq(
81
- [
82
- '/test-localtest-me-images.html',
83
- '/images/img-relative.png',
84
- ],
85
- )
86
- expect(loader.snapshot_resources.collect(&:is_root)).to eq([true, nil])
87
- end
88
- end
89
- describe '#_should_include_url?' do
90
- it 'returns true for valid, local URLs' do
91
- expect(loader._should_include_url?('http://localhost/')).to eq(true)
92
- expect(loader._should_include_url?('http://localhost:123/')).to eq(true)
93
- expect(loader._should_include_url?('http://localhost/foo')).to eq(true)
94
- expect(loader._should_include_url?('http://localhost:123/foo')).to eq(true)
95
- expect(loader._should_include_url?('http://localhost/foo/test.html')).to eq(true)
96
- expect(loader._should_include_url?('http://127.0.0.1/')).to eq(true)
97
- expect(loader._should_include_url?('http://127.0.0.1:123/')).to eq(true)
98
- expect(loader._should_include_url?('http://127.0.0.1/foo')).to eq(true)
99
- expect(loader._should_include_url?('http://127.0.0.1:123/foo')).to eq(true)
100
- expect(loader._should_include_url?('http://127.0.0.1/foo/test.html')).to eq(true)
101
- expect(loader._should_include_url?('http://0.0.0.0/foo/test.html')).to eq(true)
102
- # Also works for paths:
103
- expect(loader._should_include_url?('/')).to eq(true)
104
- expect(loader._should_include_url?('/foo')).to eq(true)
105
- expect(loader._should_include_url?('/foo/test.png')).to eq(true)
106
- end
107
- it 'returns false for invalid URLs' do
108
- expect(loader._should_include_url?('')).to eq(false)
109
- expect(loader._should_include_url?('http://local host/foo')).to eq(false)
110
- expect(loader._should_include_url?('bad-url/')).to eq(false)
111
- expect(loader._should_include_url?('bad-url/foo/test.html')).to eq(false)
112
- end
113
- it 'returns false for data URLs' do
114
- expect(loader._should_include_url?('data:image/gif;base64,R0')).to eq(false)
115
- end
116
-
117
- context 'when loader is initialised with asset hostnames' do
118
- let(:asset_hostnames) { ['dev.local'] }
119
-
120
- context 'with the same port' do
121
- it 'returns in accordance with asset_hostnames' do
122
- expect(loader._should_include_url?('http://dev.local/')).to eq(true)
123
- expect(loader._should_include_url?('http://dev.local/foo')).to eq(true)
124
-
125
- expect(loader._should_include_url?('http://other.local/')).to eq(false)
126
- end
127
- end
128
- context 'with different port' do
129
- it 'returns in accordance with asset_hostnames' do
130
- expect(loader._should_include_url?('http://dev.local:4321/foo')).to eq(true)
131
- expect(loader._should_include_url?('http://other.local:1234/foo')).to eq(false)
132
- end
133
- end
134
- context 'https' do
135
- it 'returns in accordance with asset_hostnames' do
136
- expect(loader._should_include_url?('https://dev.local/foo')).to eq(true)
137
- expect(loader._should_include_url?('https://other.local/foo')).to eq(false)
138
- end
139
- end
140
- end
141
- context 'for nonlocal hosts' do
142
- let(:fake_page) { OpenStruct.new(current_url: 'http://foo:123/') }
143
-
144
- it 'returns true for the same host port' do
145
- expect(loader._should_include_url?('http://foo:123/')).to eq(true)
146
- expect(loader._should_include_url?('http://foo:123/bar')).to eq(true)
147
- end
148
- it 'returns false for different port' do
149
- expect(loader._should_include_url?('http://foo/')).to eq(false)
150
- expect(loader._should_include_url?('http://foo/bar')).to eq(false)
151
- expect(loader._should_include_url?('http://foo:1234/')).to eq(false)
152
- expect(loader._should_include_url?('http://foo:1234/bar')).to eq(false)
153
- end
154
- it 'returns false for different host' do
155
- expect(loader._should_include_url?('http://afoo:123/')).to eq(false)
156
- expect(loader._should_include_url?('http://afoo:123/bar')).to eq(false)
157
- end
158
- end
159
- end
160
- describe '#_get_css_resources', type: :feature, js: true do
161
- it 'includes all linked and imported stylesheets' do
162
- visit '/test-css.html'
163
-
164
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
165
- resources = loader.send(:_get_css_resources)
166
-
167
- resource = find_resource(resources, '/css/base.css')
168
-
169
- expect(resource.content).to include('.colored-by-base { color: red; }')
170
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
171
-
172
- resource = find_resource(resources, '/css/simple-imports.css')
173
- expect(resource.content).to include("@import url('imports.css');")
174
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
175
-
176
- resource = find_resource(resources, '/css/imports.css')
177
- expect(resource.content).to include('.colored-by-imports { color: red; }')
178
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
179
-
180
- resource = find_resource(resources, '/css/level0-imports.css')
181
- expect(resource.content).to include("@import url('level1-imports.css')")
182
- expect(resource.content).to include('.colored-by-level0-imports { color: red; }')
183
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
184
-
185
- resource = find_resource(resources, '/css/level1-imports.css')
186
- expect(resource.content).to include("@import url('level2-imports.css')")
187
- expect(resource.content).to include('.colored-by-level1-imports { color: red; }')
188
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
189
-
190
- resource = find_resource(resources, '/css/level2-imports.css')
191
- expect(resource.content).to include('.colored-by-level2-imports { color: red; }')
192
- expect(resource.sha).to eq(Digest::SHA256.hexdigest(resource.content))
193
-
194
- expect(resources.length).to eq(6)
195
- expect(resources.collect(&:mimetype).uniq).to eq(['text/css'])
196
- expect(resources.collect(&:is_root).uniq).to match_array([nil])
197
- end
198
- end
199
- describe '#_get_image_resources', type: :feature, js: true do
200
- it 'includes all images' do
201
- visit '/test-images.html'
202
-
203
- loader = Percy::Capybara::Loaders::NativeLoader.new(page: page)
204
- loader.instance_variable_set(:@urls_referred_by_css, [])
205
- resources = loader.send(:_get_image_resources)
206
-
207
- # The order of these is just for convenience, they match the order in test-images.html.
208
-
209
- resource = find_resource(resources, '/images/img-relative.png')
210
- path = File.expand_path('../../client/test_data/images/img-relative.png', __FILE__)
211
- content = File.read(path)
212
- expect(resource.mimetype).to eq('image/png')
213
- expected_sha = Digest::SHA256.hexdigest(content)
214
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
215
- expect(resource.sha).to eq(expected_sha)
216
-
217
- resource = find_resource(resources, '/images/img-relative-to-root.png')
218
- path = File.expand_path('../../client/test_data/images/img-relative-to-root.png', __FILE__)
219
- content = File.read(path)
220
- expect(resource.mimetype).to eq('image/png')
221
- expected_sha = Digest::SHA256.hexdigest(content)
222
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
223
- expect(resource.sha).to eq(expected_sha)
224
-
225
- resource = find_resource(resources, '/images/percy.svg')
226
- path = File.expand_path('../../client/test_data/images/percy.svg', __FILE__)
227
- content = File.read(path)
228
- # In Ruby 1.9.3 the SVG mimetype is not registered so our mini ruby webserver doesn't serve
229
- # the correct content type. Allow either to work here so we can test older Rubies fully.
230
- expect(resource.mimetype).to match(/image\/svg\+xml|application\/octet-stream/)
231
- expected_sha = Digest::SHA256.hexdigest(content)
232
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
233
- expect(resource.sha).to eq(expected_sha)
234
-
235
- resource = find_resource(resources, '/images/bg-relative.png')
236
- path = File.expand_path('../../client/test_data/images/bg-relative.png', __FILE__)
237
- content = File.read(path)
238
- expect(resource.mimetype).to eq('image/png')
239
- expected_sha = Digest::SHA256.hexdigest(content)
240
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
241
- expect(resource.sha).to eq(expected_sha)
242
-
243
- resource = find_resource(resources, '/images/bg-relative-to-root.png')
244
- path = File.expand_path('../../client/test_data/images/bg-relative-to-root.png', __FILE__)
245
- content = File.read(path)
246
- expect(resource.mimetype).to eq('image/png')
247
- expected_sha = Digest::SHA256.hexdigest(content)
248
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
249
- expect(resource.sha).to eq(expected_sha)
250
-
251
- resource = find_resource(resources, '/images/bg-stacked.png')
252
- path = File.expand_path('../../client/test_data/images/bg-stacked.png', __FILE__)
253
- content = File.read(path)
254
- expect(resource.mimetype).to eq('image/png')
255
- expected_sha = Digest::SHA256.hexdigest(content)
256
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
257
- expect(resource.sha).to eq(expected_sha)
258
-
259
- resource = find_resource(resources, '/images/srcset-base.png')
260
- path = File.expand_path('../../client/test_data/images/srcset-base.png', __FILE__)
261
- content = File.read(path)
262
- expect(resource.mimetype).to eq('image/png')
263
- expected_sha = Digest::SHA256.hexdigest(content)
264
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
265
- expect(resource.sha).to eq(expected_sha)
266
-
267
- resource = find_resource(resources, '/images/srcset-first.png')
268
- path = File.expand_path('../../client/test_data/images/srcset-first.png', __FILE__)
269
- content = File.read(path)
270
- expect(resource.mimetype).to eq('image/png')
271
- expected_sha = Digest::SHA256.hexdigest(content)
272
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
273
- expect(resource.sha).to eq(expected_sha)
274
-
275
- resource = find_resource(resources, '/images/srcset-second.png')
276
- path = File.expand_path('../../client/test_data/images/srcset-second.png', __FILE__)
277
- content = File.read(path)
278
- expect(resource.mimetype).to eq('image/png')
279
- expected_sha = Digest::SHA256.hexdigest(content)
280
- expect(Digest::SHA256.hexdigest(resource.content)).to eq(expected_sha)
281
- expect(resource.sha).to eq(expected_sha)
282
-
283
- resource_urls = resources.collect(&:resource_url)
284
- expect(resource_urls).to match_array(
285
- [
286
- '/images/img-relative.png',
287
- '/images/img-relative-to-root.png',
288
- '/images/percy.svg',
289
- '/images/srcset-base.png',
290
- '/images/srcset-first.png',
291
- '/images/srcset-second.png',
292
- '/images/bg-relative.png',
293
- '/images/bg-relative-to-root.png',
294
- '/images/bg-stacked.png',
295
- ],
296
- )
297
- expect(resources.collect(&:is_root).uniq).to match_array([nil])
298
- end
299
- end
300
- end