capybara-webmock 0.4.4 → 0.5.0
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 +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
|