proxy_tester 0.0.4 → 0.0.5
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.
- data/.gitignore +3 -1
- data/.yardopts +5 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +15 -1
- data/README.md +44 -0
- data/Rakefile +7 -0
- data/config/license_finder.yml +9 -0
- data/doc/licenses/dependencies.db +0 -0
- data/lib/proxy_tester/git_repository.rb +1 -1
- data/lib/proxy_tester/rspec/helper.rb +23 -6
- data/lib/proxy_tester/rspec/matchers/have_requests_with_status_code.rb +42 -0
- data/lib/proxy_tester/rspec/matchers/reference_domains.rb +37 -0
- data/lib/proxy_tester/rspec_runner.rb +7 -8
- data/lib/proxy_tester/user_database.rb +2 -2
- data/lib/proxy_tester/version.rb +1 -1
- data/lib/proxy_tester.rb +2 -0
- data/spec/matchers/have_requests_with_status_code_spec.rb +26 -0
- data/spec/matchers/reference_domains_spec.rb +26 -0
- data/spec/{proxy_tester_spec_helper_spec.rb → rspec_helper_spec.rb} +33 -0
- data/spec/support/capybara.rb +3 -0
- data/spec/support/environment.rb +38 -4
- metadata +13 -4
data/.gitignore
CHANGED
data/.yardopts
ADDED
data/Gemfile
CHANGED
@@ -35,5 +35,6 @@ gem 'versionomy', group: [:development, :test], require: false
|
|
35
35
|
gem 'activesupport', '~> 4.0.0', group: [:development, :test], require: false
|
36
36
|
gem 'sinatra', group: [:development, :test]
|
37
37
|
gem 'foreman', group: [:development, :test], require: false
|
38
|
+
gem 'license_finder', group: [:development, :test], require: false
|
38
39
|
|
39
40
|
gem 'awesome_print', group: [:development, :test], require: 'ap'
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
proxy_tester (0.0.
|
4
|
+
proxy_tester (0.0.5)
|
5
5
|
activerecord (~> 4.0)
|
6
6
|
activesupport (~> 4.0)
|
7
7
|
addressable
|
@@ -103,14 +103,26 @@ GEM
|
|
103
103
|
gherkin (2.12.2)
|
104
104
|
multi_json (~> 1.3)
|
105
105
|
highline (1.6.21)
|
106
|
+
httparty (0.13.0)
|
107
|
+
json (~> 1.8)
|
108
|
+
multi_xml (>= 0.5.2)
|
106
109
|
i18n (0.6.9)
|
110
|
+
json (1.8.1)
|
107
111
|
libv8 (3.16.14.3)
|
112
|
+
license_finder (0.9.5.1)
|
113
|
+
bundler
|
114
|
+
httparty
|
115
|
+
rake
|
116
|
+
sequel
|
117
|
+
sqlite3
|
118
|
+
thor
|
108
119
|
method_source (0.8.2)
|
109
120
|
mime-types (2.2)
|
110
121
|
mini_portile (0.5.2)
|
111
122
|
minitest (4.7.5)
|
112
123
|
multi_json (1.9.0)
|
113
124
|
multi_test (0.0.3)
|
125
|
+
multi_xml (0.5.5)
|
114
126
|
nokogiri (1.6.1)
|
115
127
|
mini_portile (~> 0.5.0)
|
116
128
|
poltergeist (1.5.0)
|
@@ -150,6 +162,7 @@ GEM
|
|
150
162
|
rspec-mocks (2.14.6)
|
151
163
|
ruby-progressbar (1.4.2)
|
152
164
|
rugged (0.19.0)
|
165
|
+
sequel (4.9.0)
|
153
166
|
simplecov (0.8.2)
|
154
167
|
docile (~> 1.1.0)
|
155
168
|
multi_json
|
@@ -202,6 +215,7 @@ DEPENDENCIES
|
|
202
215
|
filegen
|
203
216
|
foreman
|
204
217
|
fuubar
|
218
|
+
license_finder
|
205
219
|
poltergeist
|
206
220
|
proxy_tester!
|
207
221
|
pry
|
data/README.md
CHANGED
@@ -479,6 +479,7 @@ end
|
|
479
479
|
|
480
480
|
Set the user used to connect to the proxy.
|
481
481
|
|
482
|
+
*Lookup user password using `users.csv`*
|
482
483
|
|
483
484
|
```ruby
|
484
485
|
it 'blocks www.example.org for user "user1"' do
|
@@ -492,6 +493,49 @@ it 'blocks www.example.org for user "user1"' do
|
|
492
493
|
end
|
493
494
|
```
|
494
495
|
|
496
|
+
*Ask user for user name and user password*
|
497
|
+
|
498
|
+
```ruby
|
499
|
+
it 'blocks www.example.org for user' do
|
500
|
+
use_proxy subject
|
501
|
+
use_user :ask
|
502
|
+
|
503
|
+
visit 'http://www.example.org'
|
504
|
+
|
505
|
+
expect(page).to have_content('Access forbidden')
|
506
|
+
expect(page.status_code).to eq 403
|
507
|
+
end
|
508
|
+
```
|
509
|
+
|
510
|
+
*Ask user for user password*
|
511
|
+
|
512
|
+
```ruby
|
513
|
+
it 'blocks www.example.org for user' do
|
514
|
+
use_proxy subject
|
515
|
+
use_user 'user', :ask_password
|
516
|
+
|
517
|
+
visit 'http://www.example.org'
|
518
|
+
|
519
|
+
expect(page).to have_content('Access forbidden')
|
520
|
+
expect(page.status_code).to eq 403
|
521
|
+
end
|
522
|
+
```
|
523
|
+
|
524
|
+
*Build a special user name based on ENV*
|
525
|
+
|
526
|
+
```ruby
|
527
|
+
it 'blocks www.example.org for user' do
|
528
|
+
use_proxy subject
|
529
|
+
use_user 'user', :credential_merging
|
530
|
+
# => ENV['USER']-user
|
531
|
+
|
532
|
+
visit 'http://www.example.org'
|
533
|
+
|
534
|
+
expect(page).to have_content('Access forbidden')
|
535
|
+
expect(page.status_code).to eq 403
|
536
|
+
end
|
537
|
+
```
|
538
|
+
|
495
539
|
* use_client_ip
|
496
540
|
|
497
541
|
Set the client ip address used during proxy pac evaluation.
|
data/Rakefile
CHANGED
Binary file
|
@@ -16,7 +16,7 @@ module ProxyTester
|
|
16
16
|
@null_file = null_file
|
17
17
|
|
18
18
|
rescue Rugged::RepositoryError
|
19
|
-
raise Exceptions::RepositoryDoesNotExist,
|
19
|
+
raise Exceptions::RepositoryDoesNotExist, JSON.dump(repository: storage_path)
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.create(storage_path)
|
@@ -61,18 +61,35 @@ module ProxyTester
|
|
61
61
|
begin
|
62
62
|
super(url)
|
63
63
|
rescue ::Capybara::Poltergeist::TimeoutError
|
64
|
-
raise ProxyTester::Exceptions::FetchUrlTimeout
|
64
|
+
raise ProxyTester::Exceptions::FetchUrlTimeout, JSON.dump(url: url)
|
65
65
|
end
|
66
66
|
|
67
67
|
end
|
68
68
|
|
69
|
-
def use_user(name)
|
69
|
+
def use_user(name, options = nil)
|
70
70
|
@__proxy ||= ProxyTester::CapybaraProxy.new
|
71
|
-
proxy.user = ProxyTester::User.find_by!(name: name)
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
if name == :ask
|
73
|
+
user_name = HighLine.new.ask('Please enter username: ')
|
74
|
+
user_password = HighLine.new.ask('Please enter user password: ') { |q| q.echo = '*' }
|
75
|
+
|
76
|
+
proxy.user = ProxyTester::User.new(name: user_name, password: user_password)
|
77
|
+
|
78
|
+
elsif options == :ask_password
|
79
|
+
user_password = HighLine.new.ask('Please enter user password: ') { |q| q.echo = '*' }
|
80
|
+
|
81
|
+
proxy.user = ProxyTester::User.new(name: name, password: user_password)
|
82
|
+
elsif options == :credential_merging
|
83
|
+
user_password = HighLine.new.ask('Please enter user password: ') { |q| q.echo = '*' }
|
84
|
+
proxy.user = ProxyTester::User.new(name: "#{ENV['USER']}-#{name}", password: user_password)
|
85
|
+
else
|
86
|
+
begin
|
87
|
+
proxy.user = ProxyTester::User.find_by!(name: name)
|
88
|
+
rescue ActiveRecord::RecordNotFound
|
89
|
+
ProxyTester.ui_logger.fatal "User \"#{name}\" could not be found. Please make use he's in the user database. Exiting."
|
90
|
+
raise ProxyTester::Exceptions::ProxyUserInvalid, JSON.dump(user: name)
|
91
|
+
end
|
92
|
+
end
|
76
93
|
end
|
77
94
|
|
78
95
|
def use_client_ip(ip)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
RSpec::Matchers.define :have_requests_with_status_code do |expected|
|
3
|
+
match do |actual|
|
4
|
+
domains_eq? actual, expected
|
5
|
+
end
|
6
|
+
|
7
|
+
failure_message_for_should do |actual|
|
8
|
+
expected_domains = format_domains(expected)
|
9
|
+
actual_domains = format_domains(extract_domains(actual))
|
10
|
+
|
11
|
+
"expected that \"#{actual.current_url}\" references with the given http status codes:\n#{expected_domains}\n\nBut it references with the given http status codes:\n#{actual_domains}\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
failure_message_for_should_not do |actual|
|
15
|
+
expected_domains = format_domains(expected)
|
16
|
+
actual_domains = format_domains(extract_domains(actual))
|
17
|
+
|
18
|
+
"expected that \"#{actual.current_url}\" not references domains with the given http status codes:\n#{expected_domains}\n\nBut it references with the given http status codes:\n#{actual_domains}\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
description do
|
22
|
+
"to reference domains with the given http status codes:\n#{format_domains(expected)}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def domains_eq?(actual, expected)
|
26
|
+
actual_domains = extract_domains(actual)
|
27
|
+
|
28
|
+
expected.all? { |key, value| Array(actual_domains[key]) == Array(value) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def extract_domains(page)
|
32
|
+
page.driver.network_traffic.reduce({}) { |memo, o| memo[Addressable::URI.parse(o.url).host] = get_status_codes(o.response_parts); memo}
|
33
|
+
end
|
34
|
+
|
35
|
+
def format_domains(domains)
|
36
|
+
domains.collect { |key, value| format "* %s (%s)", key, Array(value).collect { |s| "\"#{s}\""}.join(', ')}.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_status_codes(response_parts)
|
40
|
+
response_parts.collect { |rp| rp.status }.uniq
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec::Matchers.define :reference_domains do |expected|
|
4
|
+
match do |actual|
|
5
|
+
domains_eq? actual, expected
|
6
|
+
end
|
7
|
+
|
8
|
+
failure_message_for_should do |actual|
|
9
|
+
expected_domains = format_domains(expected)
|
10
|
+
actual_domains = format_domains(extract_domains(actual))
|
11
|
+
|
12
|
+
"expected that \"#{actual.current_url}\" references:\n#{expected_domains}\n\nBut it references:\n#{actual_domains}\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
failure_message_for_should_not do |actual|
|
16
|
+
expected_domains = format_domains(expected)
|
17
|
+
actual_domains = format_domains(extract_domains(actual))
|
18
|
+
|
19
|
+
"expected that \"#{actual.current_url}\" not references:\n#{expected_domains}\n\nBut it references:\n#{actual_domains}\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
description do
|
23
|
+
"to reference domains:\n#{format_domains(expected)}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def domains_eq?(actual, expected)
|
27
|
+
(extract_domains(actual) - expected).blank?
|
28
|
+
end
|
29
|
+
|
30
|
+
def extract_domains(page)
|
31
|
+
page.driver.network_traffic.collect { |o| Addressable::URI.parse(o.url).host }.uniq
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_domains(domains)
|
35
|
+
domains.sort.collect { |d| format "* %s", d}.join("\n")
|
36
|
+
end
|
37
|
+
end
|
@@ -16,16 +16,15 @@ module ProxyTester
|
|
16
16
|
def run(tags)
|
17
17
|
ProxyTester.load_user_database
|
18
18
|
ProxyTester.clear_environment
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
19
|
+
|
20
|
+
options = []
|
21
|
+
options << '--color'
|
22
|
+
options = options + ['--format', 'Fuubar' ]
|
23
|
+
options = options + ['--order', 'rand' ]
|
24
|
+
options = options + ['--tag' ] + tags
|
26
25
|
|
27
26
|
$LOAD_PATH << test_cases_directory
|
28
|
-
RSpec::Core::Runner.run(spec_files)
|
27
|
+
RSpec::Core::Runner.run(options + spec_files)
|
29
28
|
end
|
30
29
|
|
31
30
|
private
|
@@ -12,13 +12,13 @@ module ProxyTester
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def create_users(creator)
|
15
|
-
|
15
|
+
fail Exceptions::UserFileNotFound, JSON.dump(file: file) unless ::File.exist? file
|
16
16
|
|
17
17
|
CSV.foreach(file, headers: true) do |r|
|
18
18
|
creator.create! name: r['name'], password: r['password']
|
19
19
|
end
|
20
20
|
rescue ActiveRecord::RecordInvalid => err
|
21
|
-
raise Exceptions::UserRecordInvalid, message: err.message
|
21
|
+
raise Exceptions::UserRecordInvalid, JSON.dump(message: err.message)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/proxy_tester/version.rb
CHANGED
data/lib/proxy_tester.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Have Requests with status code Matcher' do
|
5
|
+
it 'checks if a site references a given list of domains with results in a given status code' do
|
6
|
+
domains = {
|
7
|
+
'example.org' => 200,
|
8
|
+
}
|
9
|
+
|
10
|
+
use_proxy 'localhost:3128'
|
11
|
+
visit('http://example.org')
|
12
|
+
|
13
|
+
expect(page).to have_requests_with_status_code domains
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'checks if a site not references a given list of domains' do
|
17
|
+
domains = {
|
18
|
+
'example.org' => 500,
|
19
|
+
}
|
20
|
+
|
21
|
+
use_proxy 'localhost:3128'
|
22
|
+
visit('http://example.org')
|
23
|
+
|
24
|
+
expect(page).not_to have_requests_with_status_code domains
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Reference Domain Matcher' do
|
5
|
+
it 'checks if a site references a given list of domains' do
|
6
|
+
domains = [
|
7
|
+
'example.org',
|
8
|
+
]
|
9
|
+
|
10
|
+
use_proxy 'localhost:3128'
|
11
|
+
visit('http://example.org')
|
12
|
+
|
13
|
+
expect(page).to reference_domains domains
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'checks if a site not references a given list of domains' do
|
17
|
+
domains = [
|
18
|
+
'asdf',
|
19
|
+
]
|
20
|
+
|
21
|
+
use_proxy 'localhost:3128'
|
22
|
+
visit('http://example.org')
|
23
|
+
|
24
|
+
expect(page).not_to reference_domains domains
|
25
|
+
end
|
26
|
+
end
|
@@ -133,5 +133,38 @@ describe 'Spec helper' do
|
|
133
133
|
end
|
134
134
|
}.to raise_error Exceptions::ProxyUserInvalid
|
135
135
|
end
|
136
|
+
|
137
|
+
it 'asks for user' do
|
138
|
+
silence :stdout do
|
139
|
+
mock_io :stdin, 'user', 'password' do
|
140
|
+
use_user :ask
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
expect(proxy.user.name).to eq('user')
|
145
|
+
expect(proxy.user.password).to eq('password')
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'asks for user password' do
|
149
|
+
silence :stdout do
|
150
|
+
mock_io :stdin, 'my_password' do
|
151
|
+
use_user 'user', :ask_password
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
expect(proxy.user.name).to eq('user')
|
156
|
+
expect(proxy.user.password).to eq('my_password')
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'asks for user password and uses local user as base' do
|
160
|
+
silence :stdout do
|
161
|
+
mock_io :stdin, 'my_password' do
|
162
|
+
use_user 'user', :credential_merging
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
expect(proxy.user.name).to eq("#{ENV['USER']}-user")
|
167
|
+
expect(proxy.user.password).to eq('my_password')
|
168
|
+
end
|
136
169
|
end
|
137
170
|
end
|
data/spec/support/capybara.rb
CHANGED
data/spec/support/environment.rb
CHANGED
@@ -5,15 +5,49 @@ module ProxyTester
|
|
5
5
|
module SpecHelper
|
6
6
|
module Environment
|
7
7
|
include FeduxOrg::Stdlib::Environment
|
8
|
+
|
8
9
|
alias_method :with_environment, :isolated_environment
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
private
|
12
|
+
|
13
|
+
def set_stdin(obj)
|
14
|
+
$stdin = obj
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_stderr(obj)
|
18
|
+
$stderr = obj
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_stdout(obj)
|
22
|
+
$stdout = obj
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_stdin
|
26
|
+
$stdin
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_stderr
|
30
|
+
$stderr
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_stdout
|
34
|
+
$stdout
|
35
|
+
end
|
36
|
+
|
37
|
+
public
|
38
|
+
|
39
|
+
def mock_io(io, *args, &block)
|
40
|
+
raise RuntimeError, "Unsupported io: #{io}, allowed: stderr, stdin, stdout" unless [:stderr, :stdout, :stdin].include? io
|
41
|
+
|
42
|
+
old_io = send("get_#{io}")
|
43
|
+
|
44
|
+
io_obj = send("set_#{io}", StringIO.new)
|
45
|
+
io_obj.puts(args.shift) until args.blank?
|
46
|
+
io_obj.rewind
|
13
47
|
|
14
48
|
block.call
|
15
49
|
ensure
|
16
|
-
|
50
|
+
io_obj = send("set_#{io}", old_io)
|
17
51
|
end
|
18
52
|
end
|
19
53
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proxy_tester
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-04-
|
12
|
+
date: 2014-04-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -263,6 +263,7 @@ files:
|
|
263
263
|
- .rdebugrc
|
264
264
|
- .rspec
|
265
265
|
- .simplecov
|
266
|
+
- .yardopts
|
266
267
|
- Gemfile
|
267
268
|
- Gemfile.lock
|
268
269
|
- LICENSE.txt
|
@@ -271,7 +272,9 @@ files:
|
|
271
272
|
- Rakefile
|
272
273
|
- bin/proxy_tester
|
273
274
|
- config.yaml
|
275
|
+
- config/license_finder.yml
|
274
276
|
- db/migrate/20140314_create_environment.rb
|
277
|
+
- doc/licenses/dependencies.db
|
275
278
|
- features/.keep
|
276
279
|
- features/add_test_case.feature
|
277
280
|
- features/step_definitions.rb
|
@@ -321,6 +324,8 @@ files:
|
|
321
324
|
- lib/proxy_tester/remote_repository.rb
|
322
325
|
- lib/proxy_tester/reporters/fetch_urls.rb
|
323
326
|
- lib/proxy_tester/rspec/helper.rb
|
327
|
+
- lib/proxy_tester/rspec/matchers/have_requests_with_status_code.rb
|
328
|
+
- lib/proxy_tester/rspec/matchers/reference_domains.rb
|
324
329
|
- lib/proxy_tester/rspec_runner.rb
|
325
330
|
- lib/proxy_tester/template_file.rb
|
326
331
|
- lib/proxy_tester/template_repository.rb
|
@@ -357,10 +362,12 @@ files:
|
|
357
362
|
- spec/git_repository_spec.rb
|
358
363
|
- spec/http_proxy_spec.rb
|
359
364
|
- spec/main_spec.rb
|
365
|
+
- spec/matchers/have_requests_with_status_code_spec.rb
|
366
|
+
- spec/matchers/reference_domains_spec.rb
|
360
367
|
- spec/pac_result_spec.rb
|
361
|
-
- spec/proxy_tester_spec_helper_spec.rb
|
362
368
|
- spec/remote_repository_spec.rb
|
363
369
|
- spec/reporters/fetch_urls_spec.rb
|
370
|
+
- spec/rspec_helper_spec.rb
|
364
371
|
- spec/rspec_runner_spec.rb
|
365
372
|
- spec/spec_helper.rb
|
366
373
|
- spec/support/capybara.rb
|
@@ -434,10 +441,12 @@ test_files:
|
|
434
441
|
- spec/git_repository_spec.rb
|
435
442
|
- spec/http_proxy_spec.rb
|
436
443
|
- spec/main_spec.rb
|
444
|
+
- spec/matchers/have_requests_with_status_code_spec.rb
|
445
|
+
- spec/matchers/reference_domains_spec.rb
|
437
446
|
- spec/pac_result_spec.rb
|
438
|
-
- spec/proxy_tester_spec_helper_spec.rb
|
439
447
|
- spec/remote_repository_spec.rb
|
440
448
|
- spec/reporters/fetch_urls_spec.rb
|
449
|
+
- spec/rspec_helper_spec.rb
|
441
450
|
- spec/rspec_runner_spec.rb
|
442
451
|
- spec/spec_helper.rb
|
443
452
|
- spec/support/capybara.rb
|