rspec-webservice_matchers 4.0.0 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +0 -1
- data/README.md +0 -1
- data/Rakefile +1 -2
- data/lib/rspec/webservice_matchers/be_status.rb +20 -0
- data/lib/rspec/webservice_matchers/be_up.rb +20 -0
- data/lib/rspec/webservice_matchers/enforce_https_everywhere.rb +50 -0
- data/lib/rspec/webservice_matchers/have_a_valid_cert.rb +23 -0
- data/lib/rspec/webservice_matchers/redirect_permanently_to.rb +40 -0
- data/lib/rspec/webservice_matchers/redirect_temporarily_to.rb +41 -0
- data/lib/rspec/webservice_matchers/util.rb +83 -0
- data/lib/rspec/webservice_matchers/version.rb +1 -1
- data/lib/rspec/webservice_matchers.rb +6 -248
- data/rspec-webservice_matchers.gemspec +2 -1
- data/spec/rspec/webservice_matchers/protcol_spec.rb +2 -1
- data/spec/rspec/webservice_matchers/public_api_spec.rb +5 -4
- data/spec/rspec/webservice_matchers/ssl_spec.rb +6 -5
- metadata +13 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4356f7c49634e7a88471c05598307e27aaf5fbd
|
4
|
+
data.tar.gz: cdb55236a82a22067581d25ee24591470d658047
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c68cb9ac58edc93ae5cf0d16873a342e3d547ad32c35463fa0a315be5ac1d9d046d67ffede36e6dd4b46c254cea002504cb08ee16b8073192661e09d2fce550
|
7
|
+
data.tar.gz: df52ce370c307c92136d5da95cd3d361545d2b0674db8c19a7eca50e28d08e606becffc5a45da26d51de8d63f21c23302ff97679e529bee460b6dc87f5fe51e8
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/rspec-webservice_matchers.png)](http://badge.fury.io/rb/rspec-webservice_matchers) [![Build Status](https://travis-ci.org/dogweather/rspec-webservice_matchers.png?branch=master)](https://travis-ci.org/dogweather/rspec-webservice_matchers) [![Code Climate](https://codeclimate.com/github/dogweather/rspec-webservice_matchers.png)](https://codeclimate.com/github/dogweather/rspec-webservice_matchers)
|
4
4
|
|
5
|
-
[Issues and todo's are now managed Assembly as Bounties](https://assembly.com/think-200/bounties).
|
6
5
|
|
7
6
|
This [gem](https://rubygems.org/gems/rspec-webservice_matchers) enables you to black-box test a web app's server configuration. For example, whether its SSL certificate is correctly configured and not expired. It's a tool for doing **Test Driven Devops** (I just made that up). See [the introductory blog post](http://robb.weblaws.org/2014/01/16/new-open-source-library-for-test-driven-devops/) for more about the motivations for making this.
|
8
7
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rspec/webservice_matchers/util'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module WebserviceMatchers
|
5
|
+
# Pass when a URL returns the expected status code
|
6
|
+
# Codes are defined in http://www.rfc-editor.org/rfc/rfc2616.txt
|
7
|
+
RSpec::Matchers.define :be_status do |expected_code|
|
8
|
+
actual_code = nil
|
9
|
+
|
10
|
+
match do |url_or_domain_name|
|
11
|
+
actual_code = Util.status(url_or_domain_name)
|
12
|
+
actual_code == expected_code.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
failure_message do
|
16
|
+
"Received status #{actual_code}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rspec/webservice_matchers/util'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module WebserviceMatchers
|
5
|
+
# Pass when the response code is 200, following redirects
|
6
|
+
# if necessary.
|
7
|
+
RSpec::Matchers.define :be_up do
|
8
|
+
status = nil
|
9
|
+
|
10
|
+
match do |url_or_domain_name|
|
11
|
+
status = Util.status(url_or_domain_name, follow: true)
|
12
|
+
status == 200
|
13
|
+
end
|
14
|
+
|
15
|
+
failure_message do
|
16
|
+
"Received status #{status}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
require 'rspec/webservice_matchers/util'
|
4
|
+
module RSpec
|
5
|
+
module WebserviceMatchers
|
6
|
+
# This is a high level matcher which checks three things:
|
7
|
+
# 1. Permanent redirect
|
8
|
+
# 2. to an https url
|
9
|
+
# 3. which is correctly configured
|
10
|
+
RSpec::Matchers.define :enforce_https_everywhere do
|
11
|
+
error_msg = status = actual_protocol = actual_valid_cert = nil
|
12
|
+
|
13
|
+
match do |domain_name|
|
14
|
+
begin
|
15
|
+
status, headers = Util.head("http://#{domain_name}")
|
16
|
+
new_url = headers['location']
|
17
|
+
/^(?<protocol>https?)/ =~ new_url
|
18
|
+
actual_protocol = protocol || nil
|
19
|
+
actual_valid_cert = Util.valid_ssl_cert?(new_url)
|
20
|
+
(status == 301) &&
|
21
|
+
(actual_protocol == 'https') &&
|
22
|
+
(actual_valid_cert == true)
|
23
|
+
rescue Faraday::Error::ConnectionFailed
|
24
|
+
error_msg = 'Connection failed'
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Create a compound error message listing all of the
|
30
|
+
# relevant actual values received.
|
31
|
+
failure_message do
|
32
|
+
if !error_msg.nil?
|
33
|
+
error_msg
|
34
|
+
else
|
35
|
+
mesgs = []
|
36
|
+
if status != 301
|
37
|
+
mesgs << "received status #{status} instead of 301"
|
38
|
+
end
|
39
|
+
if !actual_protocol.nil? && actual_protocol != 'https'
|
40
|
+
mesgs << "destination uses protocol #{actual_protocol.upcase}"
|
41
|
+
end
|
42
|
+
if !actual_valid_cert
|
43
|
+
mesgs << "there's no valid SSL certificate"
|
44
|
+
end
|
45
|
+
mesgs.join('; ').capitalize
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rspec/webservice_matchers/util'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module WebserviceMatchers
|
5
|
+
# Is https is correctly implemented?
|
6
|
+
RSpec::Matchers.define :have_a_valid_cert do
|
7
|
+
error_message = nil
|
8
|
+
|
9
|
+
match do |domain_name_or_url|
|
10
|
+
begin
|
11
|
+
Util.try_ssl_connection(domain_name_or_url)
|
12
|
+
rescue Exception => e
|
13
|
+
error_message = e.message
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
failure_message do
|
19
|
+
error_message
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rspec/webservice_matchers/util'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module WebserviceMatchers
|
5
|
+
# Do we get a 301 to the place we intend?
|
6
|
+
RSpec::Matchers.define :redirect_permanently_to do |expected|
|
7
|
+
error_message = status = actual_location = nil
|
8
|
+
|
9
|
+
match do |url_or_domain_name|
|
10
|
+
begin
|
11
|
+
status, headers = Util.head(url_or_domain_name)
|
12
|
+
actual_location = headers['location']
|
13
|
+
|
14
|
+
(status == 301) && (/#{expected}\/?/.match(actual_location))
|
15
|
+
rescue Exception => e
|
16
|
+
error_message = e.message
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
failure_message do
|
22
|
+
if !error_message.nil?
|
23
|
+
error_message
|
24
|
+
else
|
25
|
+
mesgs = []
|
26
|
+
if [302, 307].include? status
|
27
|
+
mesgs << "received a temporary redirect, status #{status}"
|
28
|
+
end
|
29
|
+
if !actual_location.nil? && ! (%r|#{expected}/?| === actual_location)
|
30
|
+
mesgs << "received location #{actual_location}"
|
31
|
+
end
|
32
|
+
if ![301, 302, 307].include? status
|
33
|
+
mesgs << "not a redirect: received status #{status}"
|
34
|
+
end
|
35
|
+
mesgs.join('; ').capitalize
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rspec/webservice_matchers/util'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module WebserviceMatchers
|
5
|
+
# Do we get a 302 or 307 to the place we intend?
|
6
|
+
RSpec::Matchers.define :redirect_temporarily_to do |expected|
|
7
|
+
include RSpec
|
8
|
+
error_message = status = actual_location = nil
|
9
|
+
|
10
|
+
match do |url_or_domain_name|
|
11
|
+
begin
|
12
|
+
status, headers = Util.head(url_or_domain_name)
|
13
|
+
actual_location = headers['location']
|
14
|
+
|
15
|
+
[302, 307].include?(status) && (/#{expected}\/?/ =~ actual_location)
|
16
|
+
rescue Exception => e
|
17
|
+
error_message = e.message
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
failure_message do
|
23
|
+
if !error_message.nil?
|
24
|
+
error_message
|
25
|
+
else
|
26
|
+
mesgs = []
|
27
|
+
if status == 301
|
28
|
+
mesgs << "received a permanent redirect, status #{status}"
|
29
|
+
end
|
30
|
+
if !actual_location.nil? && ! (%r|#{expected}/?| === actual_location)
|
31
|
+
mesgs << "received location #{actual_location}"
|
32
|
+
end
|
33
|
+
if ![301, 302, 307].include? status
|
34
|
+
mesgs << "not a redirect: received status #{status}"
|
35
|
+
end
|
36
|
+
mesgs.join('; ').capitalize
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'excon'
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
require 'pry'
|
5
|
+
|
6
|
+
# Seconds
|
7
|
+
TIMEOUT = 20
|
8
|
+
OPEN_TIMEOUT = 20
|
9
|
+
|
10
|
+
module RSpec
|
11
|
+
module WebserviceMatchers
|
12
|
+
# Refactored utility functions
|
13
|
+
module Util
|
14
|
+
def self.status(url_or_domain_name, follow: false)
|
15
|
+
head(url_or_domain_name, follow: follow)[0]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.head(url_or_domain_name, follow: false)
|
19
|
+
url = make_url(url_or_domain_name)
|
20
|
+
response = recheck_on_timeout { connection(follow: follow).head(url) }
|
21
|
+
[response.status, response.headers]
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return true if the given page has status 200,
|
25
|
+
# and follow a few redirects if necessary.
|
26
|
+
def self.up?(url_or_domain_name)
|
27
|
+
url = make_url(url_or_domain_name)
|
28
|
+
conn = connection(follow: true)
|
29
|
+
response = recheck_on_timeout { conn.head(url) }
|
30
|
+
response.status == 200
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.valid_ssl_cert?(domain_name_or_url)
|
34
|
+
try_ssl_connection(domain_name_or_url)
|
35
|
+
true
|
36
|
+
rescue
|
37
|
+
# Not serving SSL, expired, or incorrect domain name in certificate
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.try_ssl_connection(domain_name_or_url)
|
42
|
+
url = "https://#{remove_protocol(domain_name_or_url)}"
|
43
|
+
recheck_on_timeout { connection.head(url) }
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def self.connection(follow: false)
|
50
|
+
Faraday.new do |c|
|
51
|
+
c.options[:timeout] = TIMEOUT
|
52
|
+
c.options[:open_timeout] = OPEN_TIMEOUT
|
53
|
+
c.use(FaradayMiddleware::FollowRedirects, limit: 4) if follow
|
54
|
+
c.adapter :excon
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Ensure that the given string is a URL,
|
59
|
+
# making it into one if necessary.
|
60
|
+
def self.make_url(url_or_domain_name)
|
61
|
+
if %r{^https?://} =~ url_or_domain_name
|
62
|
+
url_or_domain_name
|
63
|
+
else
|
64
|
+
"http://#{url_or_domain_name}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Normalize the input: remove 'http(s)://' if it's there
|
69
|
+
def self.remove_protocol(domain_name_or_url)
|
70
|
+
%r{^https?://(?<name>.+)$} =~ domain_name_or_url
|
71
|
+
name || domain_name_or_url
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.recheck_on_timeout
|
75
|
+
begin
|
76
|
+
yield
|
77
|
+
rescue Faraday::Error::TimeoutError
|
78
|
+
yield
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,248 +1,6 @@
|
|
1
|
-
require 'rspec/webservice_matchers/
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
7
|
-
# Seconds
|
8
|
-
TIMEOUT = 20
|
9
|
-
OPEN_TIMEOUT = 20
|
10
|
-
|
11
|
-
module RSpec
|
12
|
-
# RSpec Custom Matchers
|
13
|
-
# See https://www.relishapp.com/rspec/rspec-expectations/v/2-3/docs/custom-matchers/define-matcher
|
14
|
-
module WebserviceMatchers
|
15
|
-
# Test whether https is correctly implemented
|
16
|
-
RSpec::Matchers.define :have_a_valid_cert do
|
17
|
-
error_message = nil
|
18
|
-
|
19
|
-
match do |domain_name_or_url|
|
20
|
-
begin
|
21
|
-
WebserviceMatchers.try_ssl_connection(domain_name_or_url)
|
22
|
-
true
|
23
|
-
rescue Exception => e
|
24
|
-
error_message = e.message
|
25
|
-
false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
failure_message do
|
30
|
-
error_message
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Pass successfully if we get a 301 to the place we intend.
|
35
|
-
RSpec::Matchers.define :redirect_permanently_to do |expected|
|
36
|
-
error_message = actual_status = actual_location = nil
|
37
|
-
|
38
|
-
match do |url_or_domain_name|
|
39
|
-
begin
|
40
|
-
response = WebserviceMatchers.recheck_on_timeout { WebserviceMatchers.connection.head(WebserviceMatchers.make_url url_or_domain_name) }
|
41
|
-
expected = WebserviceMatchers.make_url(expected)
|
42
|
-
actual_location = response.headers['location']
|
43
|
-
actual_status = response.status
|
44
|
-
|
45
|
-
(actual_status == 301) && (/#{expected}\/?/.match(actual_location))
|
46
|
-
rescue Exception => e
|
47
|
-
error_message = e.message
|
48
|
-
false
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
failure_message do
|
53
|
-
if !error_message.nil?
|
54
|
-
error_message
|
55
|
-
else
|
56
|
-
mesgs = []
|
57
|
-
if [302, 307].include? actual_status
|
58
|
-
mesgs << "received a temporary redirect, status #{actual_status}"
|
59
|
-
end
|
60
|
-
if !actual_location.nil? && ! (%r|#{expected}/?| === actual_location)
|
61
|
-
mesgs << "received location #{actual_location}"
|
62
|
-
end
|
63
|
-
if ![301, 302, 307].include? actual_status
|
64
|
-
mesgs << "not a redirect: received status #{actual_status}"
|
65
|
-
end
|
66
|
-
mesgs.join('; ').capitalize
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Pass successfully if we get a 302 or 307 to the place we intend.
|
72
|
-
RSpec::Matchers.define :redirect_temporarily_to do |expected|
|
73
|
-
include RSpec
|
74
|
-
error_message = actual_status = actual_location = nil
|
75
|
-
|
76
|
-
match do |url_or_domain_name|
|
77
|
-
begin
|
78
|
-
response = WebserviceMatchers.recheck_on_timeout { WebserviceMatchers.connection.head(WebserviceMatchers.make_url url_or_domain_name) }
|
79
|
-
expected = WebserviceMatchers.make_url(expected)
|
80
|
-
actual_location = response.headers['location']
|
81
|
-
actual_status = response.status
|
82
|
-
|
83
|
-
[302, 307].include?(actual_status) && (/#{expected}\/?/ =~ actual_location)
|
84
|
-
rescue Exception => e
|
85
|
-
error_message = e.message
|
86
|
-
false
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
failure_message do
|
91
|
-
if !error_message.nil?
|
92
|
-
error_message
|
93
|
-
else
|
94
|
-
mesgs = []
|
95
|
-
if actual_status == 301
|
96
|
-
mesgs << "received a permanent redirect, status #{actual_status}"
|
97
|
-
end
|
98
|
-
if !actual_location.nil? && ! (%r|#{expected}/?| === actual_location)
|
99
|
-
mesgs << "received location #{actual_location}"
|
100
|
-
end
|
101
|
-
if ![301, 302, 307].include? actual_status
|
102
|
-
mesgs << "not a redirect: received status #{actual_status}"
|
103
|
-
end
|
104
|
-
mesgs.join('; ').capitalize
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# This is a high level matcher which checks three things:
|
110
|
-
# 1. Permanent redirect
|
111
|
-
# 2. to an https url
|
112
|
-
# 3. which is correctly configured
|
113
|
-
RSpec::Matchers.define :enforce_https_everywhere do
|
114
|
-
error_msg = actual_status = actual_protocol = actual_valid_cert = nil
|
115
|
-
|
116
|
-
match do |domain_name|
|
117
|
-
begin
|
118
|
-
response = WebserviceMatchers.recheck_on_timeout { WebserviceMatchers.connection.head("http://#{domain_name}") }
|
119
|
-
new_url = response.headers['location']
|
120
|
-
actual_status = response.status
|
121
|
-
/^(?<protocol>https?)/ =~ new_url
|
122
|
-
actual_protocol = protocol || nil
|
123
|
-
actual_valid_cert = WebserviceMatchers.valid_ssl_cert?(new_url)
|
124
|
-
(actual_status == 301) &&
|
125
|
-
(actual_protocol == 'https') &&
|
126
|
-
(actual_valid_cert == true)
|
127
|
-
rescue Faraday::Error::ConnectionFailed
|
128
|
-
error_msg = 'Connection failed'
|
129
|
-
false
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Create a compound error message listing all of the
|
134
|
-
# relevant actual values received.
|
135
|
-
failure_message do
|
136
|
-
if !error_msg.nil?
|
137
|
-
error_msg
|
138
|
-
else
|
139
|
-
mesgs = []
|
140
|
-
if actual_status != 301
|
141
|
-
mesgs << "received status #{actual_status} instead of 301"
|
142
|
-
end
|
143
|
-
if !actual_protocol.nil? && actual_protocol != 'https'
|
144
|
-
mesgs << "destination uses protocol #{actual_protocol.upcase}"
|
145
|
-
end
|
146
|
-
if !actual_valid_cert
|
147
|
-
mesgs << "there's no valid SSL certificate"
|
148
|
-
end
|
149
|
-
mesgs.join('; ').capitalize
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
# Pass when a URL returns the expected status code
|
156
|
-
# Codes are defined in http://www.rfc-editor.org/rfc/rfc2616.txt
|
157
|
-
RSpec::Matchers.define :be_status do |expected_code|
|
158
|
-
actual_code = nil
|
159
|
-
|
160
|
-
match do |url_or_domain_name|
|
161
|
-
url = WebserviceMatchers.make_url(url_or_domain_name)
|
162
|
-
response = WebserviceMatchers.recheck_on_timeout { WebserviceMatchers.connection.head(url) }
|
163
|
-
actual_code = response.status
|
164
|
-
expected_code = expected_code.to_i
|
165
|
-
actual_code == expected_code
|
166
|
-
end
|
167
|
-
|
168
|
-
failure_message do
|
169
|
-
"Received status #{actual_code}"
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# Pass when the response code is 200, following redirects
|
174
|
-
# if necessary.
|
175
|
-
RSpec::Matchers.define :be_up do
|
176
|
-
actual_status = nil
|
177
|
-
|
178
|
-
match do |url_or_domain_name|
|
179
|
-
url = WebserviceMatchers.make_url(url_or_domain_name)
|
180
|
-
conn = WebserviceMatchers.connection(follow: true)
|
181
|
-
response = WebserviceMatchers.recheck_on_timeout { conn.head(url) }
|
182
|
-
actual_status = response.status
|
183
|
-
actual_status == 200
|
184
|
-
end
|
185
|
-
|
186
|
-
failure_message do
|
187
|
-
"Received status #{actual_status}"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
# Return true if the given page has status 200,
|
192
|
-
# and follow a few redirects if necessary.
|
193
|
-
def self.up?(url_or_domain_name)
|
194
|
-
url = make_url(url_or_domain_name)
|
195
|
-
conn = connection(follow: true)
|
196
|
-
response = recheck_on_timeout { conn.head(url) }
|
197
|
-
response.status == 200
|
198
|
-
end
|
199
|
-
|
200
|
-
def self.valid_ssl_cert?(domain_name_or_url)
|
201
|
-
try_ssl_connection(domain_name_or_url)
|
202
|
-
true
|
203
|
-
rescue
|
204
|
-
# Not serving SSL, expired, or incorrect domain name in certificate
|
205
|
-
false
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.try_ssl_connection(domain_name_or_url)
|
209
|
-
recheck_on_timeout { connection.head("https://#{remove_protocol(domain_name_or_url)}") }
|
210
|
-
end
|
211
|
-
|
212
|
-
|
213
|
-
private
|
214
|
-
|
215
|
-
def self.connection(follow: false)
|
216
|
-
Faraday.new do |c|
|
217
|
-
c.options[:timeout] = TIMEOUT
|
218
|
-
c.options[:open_timeout] = OPEN_TIMEOUT
|
219
|
-
c.use(FaradayMiddleware::FollowRedirects, limit: 4) if follow
|
220
|
-
c.adapter :excon
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# Ensure that the given string is a URL,
|
225
|
-
# making it into one if necessary.
|
226
|
-
def self.make_url(url_or_domain_name)
|
227
|
-
if %r{^https?://} =~ url_or_domain_name
|
228
|
-
url_or_domain_name
|
229
|
-
else
|
230
|
-
"http://#{url_or_domain_name}"
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
# Normalize the input: remove 'http(s)://' if it's there
|
235
|
-
def self.remove_protocol(domain_name_or_url)
|
236
|
-
%r{^https?://(?<name>.+)$} =~ domain_name_or_url
|
237
|
-
name || domain_name_or_url
|
238
|
-
end
|
239
|
-
|
240
|
-
def self.recheck_on_timeout
|
241
|
-
begin
|
242
|
-
yield
|
243
|
-
rescue Faraday::Error::TimeoutError
|
244
|
-
yield
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
1
|
+
require 'rspec/webservice_matchers/have_a_valid_cert'
|
2
|
+
require 'rspec/webservice_matchers/redirect_permanently_to'
|
3
|
+
require 'rspec/webservice_matchers/redirect_temporarily_to'
|
4
|
+
require 'rspec/webservice_matchers/enforce_https_everywhere'
|
5
|
+
require 'rspec/webservice_matchers/be_status'
|
6
|
+
require 'rspec/webservice_matchers/be_up'
|
@@ -17,11 +17,12 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
19
19
|
spec.require_paths = ['lib']
|
20
|
+
spec.required_ruby_version = '>= 2.1.0'
|
20
21
|
|
21
22
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
23
|
spec.add_development_dependency 'rake'
|
23
24
|
spec.add_development_dependency 'pry'
|
24
|
-
spec.add_development_dependency 'webmock'
|
25
|
+
spec.add_development_dependency 'webmock'
|
25
26
|
|
26
27
|
spec.add_runtime_dependency 'rspec', '~> 3.0'
|
27
28
|
spec.add_runtime_dependency 'excon'
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rspec/webservice_matchers'
|
3
|
+
require 'rspec/webservice_matchers/util'
|
3
4
|
|
4
5
|
describe 'be_status' do
|
5
6
|
it 'can check 200 for successful resource requests' do
|
@@ -44,7 +45,7 @@ describe 'be_up' do
|
|
44
45
|
end
|
45
46
|
|
46
47
|
it 'is available via a public API' do
|
47
|
-
expect(RSpec::WebserviceMatchers.up?('http://www.website.com/')).to be true
|
48
|
+
expect(RSpec::WebserviceMatchers::Util.up?('http://www.website.com/')).to be true
|
48
49
|
end
|
49
50
|
|
50
51
|
it 'gives relevant error output' do
|
@@ -1,13 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'rspec/webservice_matchers'
|
2
|
+
require 'rspec/webservice_matchers/util'
|
3
|
+
include RSpec::WebserviceMatchers
|
3
4
|
|
4
5
|
describe '#up?' do
|
5
6
|
it 'follows redirects when necessary' do
|
6
|
-
expect(
|
7
|
-
expect(
|
7
|
+
expect(Util.up?('perm-redirector.com')).to be_truthy
|
8
|
+
expect(Util.up?('temp-redirector.org')).to be_truthy
|
8
9
|
end
|
9
10
|
|
10
11
|
it 'retries timeout errors once' do
|
11
|
-
expect(
|
12
|
+
expect(Util.up?('http://www.timeout-once.com')).to be_truthy
|
12
13
|
end
|
13
14
|
end
|
@@ -26,11 +26,12 @@ describe 'have_a_valid_cert matcher' do
|
|
26
26
|
}.to fail_matching(/not known/i)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
# TODO: Find a good way to test this.
|
30
|
+
# it 'provides a good error message if the request times out' do
|
31
|
+
# expect {
|
32
|
+
# expect('www.myapp.com').to have_a_valid_cert
|
33
|
+
# }.to fail_matching(/(timeout)|(execution expired)/)
|
34
|
+
# end
|
34
35
|
end
|
35
36
|
|
36
37
|
# See https://www.eff.org/https-everywhere
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-webservice_matchers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robb Shecter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +136,13 @@ files:
|
|
136
136
|
- README.md
|
137
137
|
- Rakefile
|
138
138
|
- lib/rspec/webservice_matchers.rb
|
139
|
+
- lib/rspec/webservice_matchers/be_status.rb
|
140
|
+
- lib/rspec/webservice_matchers/be_up.rb
|
141
|
+
- lib/rspec/webservice_matchers/enforce_https_everywhere.rb
|
142
|
+
- lib/rspec/webservice_matchers/have_a_valid_cert.rb
|
143
|
+
- lib/rspec/webservice_matchers/redirect_permanently_to.rb
|
144
|
+
- lib/rspec/webservice_matchers/redirect_temporarily_to.rb
|
145
|
+
- lib/rspec/webservice_matchers/util.rb
|
139
146
|
- lib/rspec/webservice_matchers/version.rb
|
140
147
|
- rspec-webservice_matchers.gemspec
|
141
148
|
- spec/rspec/webservice_matchers/protcol_spec.rb
|
@@ -155,7 +162,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
162
|
requirements:
|
156
163
|
- - ">="
|
157
164
|
- !ruby/object:Gem::Version
|
158
|
-
version:
|
165
|
+
version: 2.1.0
|
159
166
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
167
|
requirements:
|
161
168
|
- - ">="
|
@@ -163,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
170
|
version: '0'
|
164
171
|
requirements: []
|
165
172
|
rubyforge_project:
|
166
|
-
rubygems_version: 2.4.
|
173
|
+
rubygems_version: 2.4.6
|
167
174
|
signing_key:
|
168
175
|
specification_version: 4
|
169
176
|
summary: Black-box web app configuration testing
|