rspec-webservice_matchers 4.9.0 → 4.12.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 +5 -5
- data/.github/workflows/ruby.yml +35 -0
- data/HISTORY.md +13 -0
- data/README.md +11 -15
- data/circle.yml +2 -0
- data/lib/rspec/webservice_matchers/be_fast.rb +2 -46
- data/lib/rspec/webservice_matchers/be_status.rb +3 -2
- data/lib/rspec/webservice_matchers/be_up.rb +2 -24
- data/lib/rspec/webservice_matchers/enforce_https_everywhere.rb +7 -6
- data/lib/rspec/webservice_matchers/have_a_valid_cert.rb +3 -2
- data/lib/rspec/webservice_matchers/redirect_helpers.rb +5 -4
- data/lib/rspec/webservice_matchers/redirect_permanently_to.rb +2 -1
- data/lib/rspec/webservice_matchers/redirect_temporarily_to.rb +2 -1
- data/lib/rspec/webservice_matchers/version.rb +2 -1
- data/lib/web_test/be_fast.rb +59 -0
- data/lib/web_test/be_up.rb +25 -0
- data/lib/web_test/util.rb +105 -0
- data/rspec-webservice_matchers.gemspec +10 -9
- data/spec/failure_matchers.rb +16 -0
- data/spec/rspec/webservice_matchers/{protcol_spec.rb → protocol_spec.rb} +5 -8
- data/spec/rspec/webservice_matchers/public_api_spec.rb +6 -5
- data/spec/rspec/webservice_matchers/redirect_spec.rb +19 -18
- data/spec/rspec/webservice_matchers/ssl_spec.rb +72 -47
- data/spec/spec_helper.rb +3 -54
- data/spec/web_mock_config.rb +54 -0
- data/spec/web_test/be_up_spec.rb +93 -0
- data/spec/web_test/util_spec.rb +6 -0
- metadata +53 -35
- data/lib/rspec/webservice_matchers/util.rb +0 -97
- data/spec/rspec/webservice_matchers/be_fast_spec.rb +0 -28
- data/spec/rspec/webservice_matchers/be_up_spec.rb +0 -94
- data/spec/rspec/webservice_matchers/page_speed_spec.rb +0 -37
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
TIMEOUT_IN_SECONDS = 5
|
6
|
+
OPEN_TIMEOUT_IN_SECONDS = 5
|
7
|
+
|
8
|
+
module WebTest
|
9
|
+
module Util
|
10
|
+
def self.error_message(errors)
|
11
|
+
return errors.message if errors.respond_to?(:message)
|
12
|
+
|
13
|
+
errors
|
14
|
+
.map(&:to_s)
|
15
|
+
.join('; ')
|
16
|
+
.capitalize
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.status(url_or_domain_name, follow: false)
|
20
|
+
code = head(url_or_domain_name, follow: follow)[0]
|
21
|
+
return code if code != 405
|
22
|
+
get(url_or_domain_name, follow: follow)[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.head(url_or_domain_name, follow: false)
|
26
|
+
request(:head, url_or_domain_name, follow: follow)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.get(url_or_domain_name, follow: false)
|
30
|
+
request(:get, url_or_domain_name, follow: follow)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.request(method, url_or_domain_name, follow: false)
|
34
|
+
url = make_url(url_or_domain_name)
|
35
|
+
response = recheck_on_timeout { connection(follow: follow).send(method, url) }
|
36
|
+
[response.status, response.headers]
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return true if the given page has status 200,
|
40
|
+
# and follow a few redirects if necessary.
|
41
|
+
def self.up?(url_or_domain_name)
|
42
|
+
url = make_url(url_or_domain_name)
|
43
|
+
conn = connection(follow: true)
|
44
|
+
response = recheck_on_timeout { conn.head(url) }
|
45
|
+
response.status == 200
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.valid_cert?(domain_name_or_url)
|
49
|
+
try_ssl_connection(domain_name_or_url)
|
50
|
+
true
|
51
|
+
rescue
|
52
|
+
# Not serving SSL, expired, or incorrect domain name in certificate
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.try_ssl_connection(domain_name_or_url)
|
57
|
+
url = "https://#{remove_protocol(domain_name_or_url)}"
|
58
|
+
recheck_on_timeout { connection.head(url) }
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
# private
|
63
|
+
|
64
|
+
def self.connection(follow: false)
|
65
|
+
Faraday.new do |c|
|
66
|
+
c.options[:timeout] = TIMEOUT_IN_SECONDS
|
67
|
+
c.options[:open_timeout] = OPEN_TIMEOUT_IN_SECONDS
|
68
|
+
c.use(FaradayMiddleware::FollowRedirects, limit: 4) if follow
|
69
|
+
c.adapter :net_http
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Ensure that the given string is a URL,
|
74
|
+
# making it into one if necessary.
|
75
|
+
def self.make_url(url_or_domain_name)
|
76
|
+
if %r{^https?://} =~ url_or_domain_name
|
77
|
+
url_or_domain_name
|
78
|
+
else
|
79
|
+
"http://#{url_or_domain_name}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return just the domain name portion of a URL if
|
84
|
+
# it's simply of the form http://name.tld
|
85
|
+
def self.make_domain_name(url_or_domain_name)
|
86
|
+
if %r{^https?://(.+)} =~ url_or_domain_name
|
87
|
+
$1
|
88
|
+
else
|
89
|
+
url_or_domain_name
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Normalize the input: remove 'http(s)://' if it's there
|
94
|
+
def self.remove_protocol(domain_name_or_url)
|
95
|
+
%r{^https?://(?<name>.+)$} =~ domain_name_or_url
|
96
|
+
name || domain_name_or_url
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.recheck_on_timeout
|
100
|
+
yield
|
101
|
+
rescue Faraday::TimeoutError
|
102
|
+
yield
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
|
-
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'rspec/webservice_matchers/version'
|
6
6
|
|
@@ -8,27 +8,28 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.name = 'rspec-webservice_matchers'
|
9
9
|
spec.version = RSpec::WebserviceMatchers::VERSION
|
10
10
|
spec.authors = ['Robb Shecter']
|
11
|
-
spec.email = ['robb@
|
11
|
+
spec.email = ['robb@public.law']
|
12
12
|
spec.description = 'Black-box web app configuration testing'
|
13
13
|
spec.summary = 'Black-box web app configuration testing'
|
14
14
|
spec.homepage = 'https://github.com/dogweather/rspec-webservice_matchers'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
17
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
|
-
spec.executables = spec.files.grep(
|
19
|
-
spec.test_files = spec.files.grep(
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ['lib']
|
21
|
-
spec.required_ruby_version = '>= 2.
|
21
|
+
spec.required_ruby_version = '>= 2.4.0'
|
22
22
|
|
23
|
-
spec.add_development_dependency 'bundler', '~>
|
23
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
24
24
|
spec.add_development_dependency 'pry'
|
25
25
|
spec.add_development_dependency 'rake'
|
26
26
|
spec.add_development_dependency 'rspec'
|
27
27
|
spec.add_development_dependency 'rspec_junit_formatter', '0.2.2'
|
28
28
|
spec.add_development_dependency 'webmock'
|
29
29
|
|
30
|
-
spec.add_runtime_dependency 'rspec', '~> 3.0'
|
31
30
|
spec.add_runtime_dependency 'faraday'
|
32
31
|
spec.add_runtime_dependency 'faraday_middleware'
|
33
|
-
spec.add_runtime_dependency '
|
32
|
+
spec.add_runtime_dependency 'rspec-core', '~> 3.0'
|
33
|
+
spec.add_runtime_dependency 'rspec-expectations', '~> 3.0'
|
34
|
+
spec.add_runtime_dependency 'validated_object', '~> 1.1.0'
|
34
35
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RSpec
|
2
|
+
# Matchers to help test RSpec matchers
|
3
|
+
module Matchers
|
4
|
+
def fail
|
5
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError)
|
6
|
+
end
|
7
|
+
|
8
|
+
def fail_with(message)
|
9
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, message)
|
10
|
+
end
|
11
|
+
|
12
|
+
def fail_matching(regex)
|
13
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, regex)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'spec_helper'
|
3
3
|
require 'rspec/webservice_matchers'
|
4
|
-
require '
|
4
|
+
require 'web_test/util'
|
5
|
+
|
5
6
|
|
6
7
|
describe 'be_status' do
|
7
8
|
it 'can check 200 for successful resource requests' do
|
@@ -30,7 +31,7 @@ describe 'be_status' do
|
|
30
31
|
}.to fail_matching(/404/)
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
+
xit 'succeeds even if the site times out on the first try' do
|
34
35
|
expect('http://www.timeout-once.com').to be_status 200
|
35
36
|
end
|
36
37
|
|
@@ -50,7 +51,7 @@ describe 'be_up' do
|
|
50
51
|
end
|
51
52
|
|
52
53
|
it 'is available via a public API' do
|
53
|
-
status =
|
54
|
+
status = WebTest::Util.up?('http://www.website.com/')
|
54
55
|
expect(status).to be true
|
55
56
|
end
|
56
57
|
|
@@ -60,11 +61,7 @@ describe 'be_up' do
|
|
60
61
|
}.to fail_matching(/^received status 404$/i)
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
+
xit 'succeeds even if the site times out on the first try' do
|
64
65
|
expect('http://www.timeout-once.com').to be_up
|
65
66
|
end
|
66
|
-
|
67
|
-
it 'works on cars.com' do
|
68
|
-
expect('http://cars.com').to be_up
|
69
|
-
end
|
70
67
|
end
|
@@ -1,15 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'spec_helper'
|
3
|
-
require '
|
3
|
+
require 'web_test/util'
|
4
|
+
|
4
5
|
include RSpec::WebserviceMatchers
|
5
6
|
|
6
7
|
describe '#up?' do
|
7
8
|
it 'follows redirects when necessary' do
|
8
|
-
expect(Util.up?('perm-redirector.com')).to be_truthy
|
9
|
-
expect(Util.up?('temp-redirector.org')).to be_truthy
|
9
|
+
expect(WebTest::Util.up?('perm-redirector.com')).to be_truthy
|
10
|
+
expect(WebTest::Util.up?('temp-redirector.org')).to be_truthy
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
-
expect(Util.up?('http://www.timeout-once.com')).to be_truthy
|
13
|
+
xit 'retries timeout errors once' do
|
14
|
+
expect(WebTest::Util.up?('http://www.timeout-once.com')).to be_truthy
|
14
15
|
end
|
15
16
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'spec_helper'
|
3
4
|
require 'rspec/webservice_matchers'
|
4
5
|
|
@@ -16,27 +17,27 @@ describe 'redirect_permanently_to' do
|
|
16
17
|
end
|
17
18
|
|
18
19
|
it 'gives a good error message for the wrong redirect type' do
|
19
|
-
expect
|
20
|
+
expect do
|
20
21
|
expect('temp-redirector.org').to redirect_permanently_to 'http://a-page.com/a/page.txt'
|
21
|
-
|
22
|
+
end.to fail_matching(/temporary/i)
|
22
23
|
end
|
23
24
|
|
24
25
|
it 'gives a good error message for a redirect to the wrong location' do
|
25
|
-
expect
|
26
|
+
expect do
|
26
27
|
expect('perm-redirector.com').to redirect_permanently_to 'http://the-wrong-site.com/'
|
27
|
-
|
28
|
+
end.to fail_matching(/location/i)
|
28
29
|
end
|
29
30
|
|
30
31
|
it 'gives a good error message for a non-redirect status' do
|
31
|
-
expect
|
32
|
+
expect do
|
32
33
|
expect('notfound.com').to redirect_permanently_to 'http://the-wrong-site.com/'
|
33
|
-
|
34
|
+
end.to fail_matching(/^not a redirect: received status 404$/i)
|
34
35
|
end
|
35
36
|
|
36
37
|
it 'gives a good error message when the hostname is bad' do
|
37
|
-
expect
|
38
|
-
expect('
|
39
|
-
|
38
|
+
expect do
|
39
|
+
expect('not-a-domain.com').to redirect_permanently_to 'http://the-wrong-site.com/'
|
40
|
+
end.to fail_matching(/not known/i)
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -54,26 +55,26 @@ describe 'redirect_temporarily_to' do
|
|
54
55
|
end
|
55
56
|
|
56
57
|
it 'gives a good error message for the wrong redirect type' do
|
57
|
-
expect
|
58
|
+
expect do
|
58
59
|
expect('perm-redirector.com').to redirect_temporarily_to 'www.website.com/'
|
59
|
-
|
60
|
+
end.to fail_matching(/permanent/i)
|
60
61
|
end
|
61
62
|
|
62
63
|
it 'gives a good error message for a redirect to the wrong location' do
|
63
|
-
expect
|
64
|
+
expect do
|
64
65
|
expect('temp-307-redirector.net').to redirect_temporarily_to 'www.nowhere.com'
|
65
|
-
|
66
|
+
end.to fail_matching(/location/i)
|
66
67
|
end
|
67
68
|
|
68
69
|
it 'gives a good error message for a non-redirect status' do
|
69
|
-
expect
|
70
|
+
expect do
|
70
71
|
expect('notfound.com').to redirect_temporarily_to 'www.nowhere.com'
|
71
|
-
|
72
|
+
end.to fail_matching(/^not a redirect: received status 404$/i)
|
72
73
|
end
|
73
74
|
|
74
75
|
it 'gives a good error message when the hostname is bad' do
|
75
|
-
expect
|
76
|
-
expect('
|
77
|
-
|
76
|
+
expect do
|
77
|
+
expect('not-a-domain.com').to redirect_temporarily_to 'www.nowhere.com'
|
78
|
+
end.to fail_matching(/not known/i)
|
78
79
|
end
|
79
80
|
end
|
@@ -1,62 +1,87 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'spec_helper'
|
3
4
|
require 'rspec/webservice_matchers'
|
4
5
|
|
5
|
-
describe '
|
6
|
-
|
7
|
-
|
8
|
-
# TODO: set up a test server for this. (?)
|
9
|
-
expect('www.eff.org').to have_a_valid_cert
|
10
|
-
end
|
6
|
+
describe 'SSL tests' do
|
7
|
+
before(:each) { WebMock.allow_net_connect! }
|
8
|
+
after(:each) { WebMock.disable_net_connect! }
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
describe 'have_a_valid_cert matcher' do
|
11
|
+
it 'passes when SSL is properly configured' do
|
12
|
+
# EFF created the HTTPS Everywhere movement
|
13
|
+
# TODO: set up a test server for this. (?)
|
14
|
+
expect('www.eff.org').to have_a_valid_cert
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
it 'fails if the server is not serving SSL at all' do
|
18
|
+
expect do
|
19
|
+
expect('neverssl.com').to have_a_valid_cert
|
20
|
+
end.to fail_matching(/Unable to verify/)
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
it 'provides a relevant error message' do
|
24
|
+
expect do
|
25
|
+
expect('neverssl.com').to have_a_valid_cert
|
26
|
+
end.to fail_matching(/(unreachable)|(no route to host)|(connection refused)|(redirect was detected)/i)
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
29
|
+
xit "provides a relevant error message when the domain name doesn't exist" do
|
30
|
+
expect do
|
31
|
+
expect('sdfgkljhsdfghjkhsdfgj.edu').to have_a_valid_cert
|
32
|
+
end.to fail_matching(/not known/i)
|
33
|
+
end
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
35
|
+
xit "provides a good error message when it's a redirect" do
|
36
|
+
expect do
|
37
|
+
# Can't figure out how to do this with WebMock.
|
38
|
+
expect('bloc.io').to have_a_valid_cert
|
39
|
+
end.to fail_matching(/redirect/i)
|
40
|
+
end
|
44
41
|
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
# TODO: Find a good way to test this.
|
43
|
+
xit 'provides a good error message if the request times out' do
|
44
|
+
expect {
|
45
|
+
expect('www.myapp.com').to have_a_valid_cert
|
46
|
+
}.to fail_matching(/(timeout)|(execution expired)/)
|
47
|
+
end
|
49
48
|
end
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
# See https://www.eff.org/https-everywhere
|
51
|
+
describe 'enforce_https_everywhere' do
|
52
|
+
it 'passes when http requests are redirected to valid https urls' do
|
53
|
+
expect('www.eff.org').to enforce_https_everywhere
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'passes when given an https url' do
|
57
|
+
expect('https://www.eff.org').to enforce_https_everywhere
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'passes when given an http url' do
|
61
|
+
expect('http://www.eff.org').to enforce_https_everywhere
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'provides a relevant error code' do
|
65
|
+
expect do
|
66
|
+
expect('neverssl.com').to enforce_https_everywhere
|
67
|
+
end.to fail_matching(/200/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'provides a relevant error code with https url' do
|
71
|
+
expect do
|
72
|
+
expect('https://neverssl.com').to enforce_https_everywhere
|
73
|
+
end.to fail_matching(/200/)
|
74
|
+
end
|
56
75
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
76
|
+
it 'provides a relevant error code with http url' do
|
77
|
+
expect do
|
78
|
+
expect('http://neverssl.com').to enforce_https_everywhere
|
79
|
+
end.to fail_matching(/200/)
|
80
|
+
end
|
81
|
+
# it "provides a relevant error message when the domain name doesn't exist" do
|
82
|
+
# expect do
|
83
|
+
# expect('asdhfjkalsdhfjklasdfhjkasdhfl.com').to enforce_https_everywhere
|
84
|
+
# end.to fail_matching(/connection failed/i)
|
85
|
+
# end
|
61
86
|
end
|
62
87
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,56 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require '
|
2
|
+
require 'web_mock_config'
|
3
|
+
require 'failure_matchers'
|
3
4
|
|
4
|
-
|
5
|
-
config.before(:each) do
|
6
|
-
WebMock.stub_request :any, 'http://a-page.com/a/page.txt'
|
7
|
-
WebMock.stub_request :any, 'www.website.com'
|
8
|
-
WebMock.stub_request(:any, /notfound.com/).to_return(status: 404)
|
9
|
-
WebMock.stub_request(:any, 'outoforder.com').to_return(status: 503)
|
10
|
-
|
11
|
-
# A host which doesn't support HEAD
|
12
|
-
WebMock.stub_request(:head, 'appengine.com').to_return(status: 405)
|
13
|
-
WebMock.stub_request(:get, 'appengine.com').to_return(status: 200)
|
14
|
-
|
15
|
-
WebMock.stub_request(:any, 'perm-redirector.com')
|
16
|
-
.to_return(status: 301, headers: { Location: 'http://www.website.com/' })
|
17
|
-
|
18
|
-
WebMock.stub_request(:any, 'temp-redirector.org')
|
19
|
-
.to_return(status: 302, headers: { Location: 'http://a-page.com/a/page.txt' })
|
20
|
-
|
21
|
-
WebMock.stub_request(:any, 'temp-307-redirector.net')
|
22
|
-
.to_return(status: 307, headers: { Location: 'http://a-page.com/a/page.txt' })
|
23
|
-
|
24
|
-
# Timeout scenarios
|
25
|
-
WebMock.stub_request(:any, 'www.timeout.com').to_timeout
|
26
|
-
WebMock.stub_request(:any, 'www.timeout-once.com').to_timeout.then.to_return(body: 'abc')
|
27
|
-
|
28
|
-
# Insights API
|
29
|
-
key = ENV['WEBSERVICE_MATCHER_INSIGHTS_KEY']
|
30
|
-
WebMock.stub_request(:get, "https://www.googleapis.com/pagespeedonline/v2/runPagespeed?key=#{key}&screenshot=false&url=http://nonstop.qa")
|
31
|
-
.with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => 'Faraday v0.9.2' })
|
32
|
-
.to_return(
|
33
|
-
status: 200,
|
34
|
-
body: IO.read('spec/fixtures/pagespeed.json'),
|
35
|
-
headers: {})
|
36
|
-
|
37
|
-
WebMock.allow_net_connect!
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
module RSpec
|
42
|
-
# Matchers to help test RSpec matchers
|
43
|
-
module Matchers
|
44
|
-
def fail
|
45
|
-
raise_error(RSpec::Expectations::ExpectationNotMetError)
|
46
|
-
end
|
47
|
-
|
48
|
-
def fail_with(message)
|
49
|
-
raise_error(RSpec::Expectations::ExpectationNotMetError, message)
|
50
|
-
end
|
51
|
-
|
52
|
-
def fail_matching(regex)
|
53
|
-
raise_error(RSpec::Expectations::ExpectationNotMetError, regex)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
5
|
+
SAMPLE_PAGESPEED_JSON_RESPONSE = 'spec/fixtures/pagespeed.json'
|