capybara-webmock 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +9 -0
- data/README.md +47 -26
- data/lib/capybara/webmock.rb +124 -14
- data/lib/capybara/webmock/config.ru +0 -7
- data/lib/capybara/webmock/proxied_request.rb +25 -0
- data/lib/capybara/webmock/proxy.rb +17 -41
- data/lib/capybara/webmock/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81553b5b1145d09248402a0c1b895df288b5e51c
|
4
|
+
data.tar.gz: 64dc84c9c2b55c7eb70f447be825fa58f6e17f43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 399fa5e03d96661d9b1370b8d0be2709a6d9ca923532fceee1ed683df95f78452a4115c95a94d2685c198614f8b6a2e710a759043163f5333cac0c4040de45be
|
7
|
+
data.tar.gz: d2558a7df70f91d5dbd6db30afa2c7fece4c0d544d2686cc4782700560257348051a0eac3f3ee882943b7d791e4881272d3fb1c3b669ea3395b024e57b9ed833
|
data/README.md
CHANGED
@@ -18,10 +18,10 @@ Use of this gem can significantly speed up the test suite. No more waiting on
|
|
18
18
|
irrelevant external requests.
|
19
19
|
|
20
20
|
`localhost`, `127.0.0.1`, `*.lvh.me`, and `lvh.me` are the only whitelisted
|
21
|
-
domains.
|
21
|
+
domains.
|
22
22
|
|
23
|
-
This gem currently supports Ruby on Rails applications
|
24
|
-
|
23
|
+
This gem currently supports Ruby on Rails applications using the Selenium
|
24
|
+
Firefox and Chrome drivers.
|
25
25
|
|
26
26
|
### Installation
|
27
27
|
|
@@ -37,7 +37,7 @@ And then execute:
|
|
37
37
|
$ bundle
|
38
38
|
```
|
39
39
|
|
40
|
-
Or install it
|
40
|
+
Or install it via the command line:
|
41
41
|
|
42
42
|
```
|
43
43
|
$ gem install capybara-webmock
|
@@ -57,8 +57,10 @@ Then in your RSpec configuration:
|
|
57
57
|
# spec/spec_helper.rb
|
58
58
|
|
59
59
|
RSpec.configure do |config|
|
60
|
-
config.before(:
|
61
|
-
|
60
|
+
config.before(:each) do |example|
|
61
|
+
if example.metadata[:type] == :feature
|
62
|
+
Capybara::Webmock.start
|
63
|
+
end
|
62
64
|
end
|
63
65
|
|
64
66
|
config.after(:suite) do
|
@@ -67,18 +69,6 @@ RSpec.configure do |config|
|
|
67
69
|
end
|
68
70
|
```
|
69
71
|
|
70
|
-
Or, your Cucumber configuration:
|
71
|
-
|
72
|
-
```ruby
|
73
|
-
# features/support/env.rb
|
74
|
-
|
75
|
-
Capybara::Webmock.start
|
76
|
-
|
77
|
-
at_exit do
|
78
|
-
Capybara::Webmock.stop
|
79
|
-
end
|
80
|
-
```
|
81
|
-
|
82
72
|
Then use the `capybara_webmock` JavaScript driver:
|
83
73
|
|
84
74
|
```ruby
|
@@ -109,17 +99,48 @@ with the following configuration:
|
|
109
99
|
Capybara::Webmock.port_number = 8080
|
110
100
|
```
|
111
101
|
|
102
|
+
During each test, you can inspect the list of proxied requests:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
it 'makes a request to /somewhere when the user visits the page' do
|
106
|
+
visit "/some-page"
|
107
|
+
expect(Capybara::Webmock.proxied_requests.any?{|req| req.path == "/somewhere" }).to be
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
112
111
|
### Development
|
113
112
|
|
114
|
-
After
|
115
|
-
|
116
|
-
|
113
|
+
After pulling down the repo, install dependencies:
|
114
|
+
|
115
|
+
```
|
116
|
+
$ bin/setup
|
117
|
+
```
|
118
|
+
|
119
|
+
Then, run the tests:
|
120
|
+
|
121
|
+
```
|
122
|
+
$ rake spec
|
123
|
+
```
|
124
|
+
|
125
|
+
For an interactive prompt that will allow you to experiment, run:
|
126
|
+
|
127
|
+
```
|
128
|
+
$ bin/console
|
129
|
+
```
|
117
130
|
|
118
|
-
To install
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
131
|
+
To install your development gem onto your local machine, run:
|
132
|
+
|
133
|
+
```
|
134
|
+
$ bundle exec rake install
|
135
|
+
```
|
136
|
+
|
137
|
+
To release a new version, update the version number in `version.rb`, then
|
138
|
+
update the git tag, push commits and tags, and publish the gem to
|
139
|
+
[rubygems.org](https://rubygems.org) with:
|
140
|
+
|
141
|
+
```
|
142
|
+
$ bundle exec rake release
|
143
|
+
```
|
123
144
|
|
124
145
|
### Contributing
|
125
146
|
|
data/lib/capybara/webmock.rb
CHANGED
@@ -1,26 +1,59 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'socket'
|
1
4
|
require 'capybara'
|
2
5
|
require 'selenium-webdriver'
|
3
6
|
require 'capybara/webmock/version'
|
4
7
|
require 'capybara/webmock/proxy'
|
8
|
+
require 'capybara/webmock/proxied_request'
|
5
9
|
|
6
10
|
module Capybara
|
7
11
|
module Webmock
|
8
12
|
class << self
|
9
|
-
|
10
|
-
attr_accessor :port_number
|
13
|
+
attr_accessor :port_number, :pid_file, :kill_timeout, :start_timeout
|
11
14
|
|
12
15
|
def start
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
if @pid.nil?
|
17
|
+
kill_old_process
|
18
|
+
gem_path = File.dirname(__FILE__)
|
19
|
+
proxy_file = File.join(gem_path, 'webmock', 'config.ru')
|
20
|
+
stdin, stdout, wait_thr = Open3.popen2e({ "PROXY_PORT_NUMBER" => port_number.to_s }, "rackup", proxy_file)
|
21
|
+
stdin.close
|
22
|
+
@stdout = stdout
|
23
|
+
@pid = wait_thr[:pid]
|
24
|
+
write_pid_file
|
25
|
+
wait_for_proxy_start
|
26
|
+
end
|
27
|
+
|
28
|
+
reset
|
17
29
|
end
|
18
30
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
31
|
+
def reset
|
32
|
+
get_output_nonblocking
|
33
|
+
@output_buf = ""
|
34
|
+
end
|
35
|
+
|
36
|
+
def proxied_requests
|
37
|
+
@output_buf += get_output_nonblocking
|
38
|
+
|
39
|
+
matches = @output_buf.sub(/\n[^\n]+\z/, '').split("\n").map do |line|
|
40
|
+
match = /\A(.+) -> (.+)\Z/.match(line)
|
41
|
+
next nil unless match
|
42
|
+
match.captures
|
23
43
|
end
|
44
|
+
|
45
|
+
matches.compact.map{ |raw_referrer, raw_uri| ProxiedRequest.new(raw_referrer, raw_uri) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
return if @pid.nil?
|
50
|
+
|
51
|
+
@stdout.close
|
52
|
+
kill_process(@pid)
|
53
|
+
remove_pid_file
|
54
|
+
|
55
|
+
@pid = nil
|
56
|
+
@stdout = nil
|
24
57
|
end
|
25
58
|
|
26
59
|
def firefox_profile
|
@@ -35,26 +68,103 @@ module Capybara
|
|
35
68
|
end
|
36
69
|
|
37
70
|
def chrome_options
|
38
|
-
|
39
|
-
options.add_argument("--proxy-server=127.0.0.1:#{port_number}")
|
40
|
-
end
|
71
|
+
{ args: "proxy-server=127.0.0.1:#{port_number}" }
|
41
72
|
end
|
42
73
|
|
43
74
|
def phantomjs_options
|
44
75
|
["--proxy=127.0.0.1:#{port_number}"]
|
45
76
|
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def wait_for_proxy_start
|
81
|
+
connected = false
|
82
|
+
(1..start_timeout).each do
|
83
|
+
begin
|
84
|
+
Socket.tcp("127.0.0.1", port_number, connect_timeout: 1) {}
|
85
|
+
connected = true
|
86
|
+
break
|
87
|
+
rescue => e
|
88
|
+
sleep 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
unless connected
|
93
|
+
raise "Unable to connect to capybara-webmock proxy on #{port_number}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_output_nonblocking
|
98
|
+
buf = ""
|
99
|
+
|
100
|
+
while true
|
101
|
+
begin
|
102
|
+
output = @stdout.read_nonblock(1024)
|
103
|
+
break if output == ""
|
104
|
+
buf += output
|
105
|
+
rescue IO::WaitReadable
|
106
|
+
break
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
buf
|
111
|
+
end
|
112
|
+
|
113
|
+
def kill_old_process
|
114
|
+
return unless File.exists?(pid_file)
|
115
|
+
old_pid = File.read(pid_file).to_i
|
116
|
+
kill_process(old_pid) if old_pid > 1
|
117
|
+
remove_pid_file
|
118
|
+
end
|
119
|
+
|
120
|
+
def kill_process(pid)
|
121
|
+
Process.kill('HUP', pid) if process_alive?(pid)
|
122
|
+
|
123
|
+
(1..kill_timeout).each do
|
124
|
+
sleep(1) if process_alive?(pid)
|
125
|
+
end
|
126
|
+
|
127
|
+
Process.kill('KILL', pid) if process_alive?(pid)
|
128
|
+
|
129
|
+
(1..kill_timeout).each do
|
130
|
+
sleep(1) if process_alive?(pid)
|
131
|
+
end
|
132
|
+
|
133
|
+
if process_alive?(pid)
|
134
|
+
raise "Unable to kill capybara-webmock process with PID #{pid}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def process_alive?(pid)
|
139
|
+
!!Process.kill(0, pid) rescue false
|
140
|
+
end
|
141
|
+
|
142
|
+
def write_pid_file
|
143
|
+
raise "Pid file #{pid_file} already exists" if File.exists?(pid_file)
|
144
|
+
FileUtils.mkdir_p(File.dirname(pid_file))
|
145
|
+
File.write(pid_file, @pid.to_s)
|
146
|
+
end
|
147
|
+
|
148
|
+
def remove_pid_file
|
149
|
+
File.delete(pid_file) if File.exists?(pid_file)
|
150
|
+
end
|
46
151
|
end
|
47
152
|
end
|
48
153
|
end
|
49
154
|
|
50
155
|
Capybara::Webmock.port_number ||= 9292
|
156
|
+
Capybara::Webmock.pid_file ||= File.join('tmp', 'pids', 'capybara_webmock_proxy.pid')
|
157
|
+
Capybara::Webmock.kill_timeout ||= 5
|
158
|
+
Capybara::Webmock.start_timeout ||= 30
|
51
159
|
|
52
160
|
Capybara.register_driver :capybara_webmock do |app|
|
53
161
|
Capybara::Selenium::Driver.new(app, browser: :firefox, profile: Capybara::Webmock.firefox_profile)
|
54
162
|
end
|
55
163
|
|
56
164
|
Capybara.register_driver :capybara_webmock_chrome do |app|
|
57
|
-
Capybara::Selenium::Driver.new(app, browser: :chrome,
|
165
|
+
Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: {
|
166
|
+
chromeOptions: Capybara::Webmock.chrome_options
|
167
|
+
})
|
58
168
|
end
|
59
169
|
|
60
170
|
Capybara.register_driver :capybara_webmock_poltergeist do |app|
|
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'capybara/webmock/proxy'
|
3
3
|
|
4
|
-
at_exit { Capybara::Webmock::Proxy.remove_pid }
|
5
|
-
|
6
|
-
trap('SIGHUP') {
|
7
|
-
Capybara::Webmock::Proxy.remove_pid
|
8
|
-
exit!
|
9
|
-
}
|
10
|
-
|
11
4
|
app = Capybara::Webmock::Proxy.new(Process.pid)
|
12
5
|
Rack::Handler::WEBrick.run(app, Port: ENV.fetch('PROXY_PORT_NUMBER', 9292))
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module Webmock
|
5
|
+
class ProxiedRequest
|
6
|
+
attr_reader :referrer, :uri
|
7
|
+
|
8
|
+
def initialize(raw_referrer, raw_uri)
|
9
|
+
@referrer = raw_referrer == "-" ? nil : URI.parse(raw_referrer)
|
10
|
+
@uri = URI.parse(raw_uri)
|
11
|
+
end
|
12
|
+
|
13
|
+
def fragment; @uri.fragment; end
|
14
|
+
def host; @uri.host; end
|
15
|
+
def hostname; @uri.hostname; end
|
16
|
+
def password; @uri.password; end
|
17
|
+
def path; @uri.path; end
|
18
|
+
def port; @uri.port; end
|
19
|
+
def query; @uri.query; end
|
20
|
+
def scheme; @uri.scheme; end
|
21
|
+
def user; @uri.user; end
|
22
|
+
def userinfo; @uri.userinfo; end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -2,12 +2,7 @@ require 'rack/proxy'
|
|
2
2
|
require 'capybara/webmock'
|
3
3
|
|
4
4
|
class Capybara::Webmock::Proxy < Rack::Proxy
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(pid)
|
8
|
-
write_pid(pid)
|
9
|
-
ensure_log_exists
|
10
|
-
end
|
5
|
+
ALLOWED_HOSTS = allowed_hosts = ['127.0.0.1', 'localhost', /(.*\.|\A)lvh.me/]
|
11
6
|
|
12
7
|
def call(env)
|
13
8
|
@streaming = true
|
@@ -16,49 +11,30 @@ class Capybara::Webmock::Proxy < Rack::Proxy
|
|
16
11
|
|
17
12
|
def perform_request(env)
|
18
13
|
request = Rack::Request.new(env)
|
19
|
-
allowed_urls = ['127.0.0.1', 'localhost', %r{(.*\.|\A)lvh.me}]
|
20
14
|
|
21
|
-
if
|
15
|
+
if allowed_host?(request.host)
|
22
16
|
super(env)
|
23
17
|
else
|
24
|
-
|
18
|
+
headers = {
|
19
|
+
'Content-Type' => 'text/html',
|
20
|
+
'Access-Control-Allow-Origin' => '*',
|
21
|
+
'Access-Control-Allow-Methods' => '*',
|
22
|
+
'Access-Control-Allow-Headers' => '*'
|
23
|
+
}
|
24
|
+
['200', headers, ['']]
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def self.remove_pid
|
29
|
-
File.delete(PID_FILE) if File.exist?(PID_FILE)
|
30
|
-
end
|
31
|
-
|
32
|
-
def rewrite_response(triplet)
|
33
|
-
status, headers, body = triplet
|
34
|
-
headers.delete "transfer-encoding"
|
35
|
-
triplet
|
36
|
-
end
|
37
|
-
|
38
28
|
private
|
39
29
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
30
|
+
def allowed_host?(host)
|
31
|
+
ALLOWED_HOSTS.any? do |allowed_host|
|
32
|
+
case allowed_host
|
33
|
+
when Regexp
|
34
|
+
allowed_host =~ host
|
35
|
+
when String
|
36
|
+
allowed_host == host
|
37
|
+
end
|
48
38
|
end
|
49
39
|
end
|
50
|
-
|
51
|
-
def write_pid(pid)
|
52
|
-
tmp_dir = 'tmp'
|
53
|
-
pid_dir = File.join(tmp_dir, 'pids')
|
54
|
-
Dir.mkdir(tmp_dir) unless Dir.exist?(tmp_dir)
|
55
|
-
Dir.mkdir(pid_dir) unless Dir.exist?(pid_dir)
|
56
|
-
File.write(PID_FILE, pid)
|
57
|
-
end
|
58
|
-
|
59
|
-
def ensure_log_exists
|
60
|
-
log_file = File.join('log', 'test.log')
|
61
|
-
Dir.mkdir('log') unless Dir.exist?('log')
|
62
|
-
File.open(log_file, 'a') { |f| f.write "" }
|
63
|
-
end
|
64
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara-webmock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jake Worth
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-09-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capybara
|
@@ -150,6 +150,7 @@ executables: []
|
|
150
150
|
extensions: []
|
151
151
|
extra_rdoc_files: []
|
152
152
|
files:
|
153
|
+
- ".circleci/config.yml"
|
153
154
|
- ".gitignore"
|
154
155
|
- ".rspec"
|
155
156
|
- CODE_OF_CONDUCT.md
|
@@ -162,6 +163,7 @@ files:
|
|
162
163
|
- capybara-webmock.gemspec
|
163
164
|
- lib/capybara/webmock.rb
|
164
165
|
- lib/capybara/webmock/config.ru
|
166
|
+
- lib/capybara/webmock/proxied_request.rb
|
165
167
|
- lib/capybara/webmock/proxy.rb
|
166
168
|
- lib/capybara/webmock/version.rb
|
167
169
|
homepage: https://github.com/hashrocket/capybara-webmock
|