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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1511010285eeb520105986a627bf40f2957fcaa
4
- data.tar.gz: a12bff84fc592bfb31774cd2c3eeb9d691d074f9
3
+ metadata.gz: 81553b5b1145d09248402a0c1b895df288b5e51c
4
+ data.tar.gz: 64dc84c9c2b55c7eb70f447be825fa58f6e17f43
5
5
  SHA512:
6
- metadata.gz: 6861262f85e84d138a83dca1c8152b601506cd702af8c58ca6cebf0b75b8c695953f53ae25338c43f253192f908bc72b2c52c31d7155f539cfed6eb400ae9799
7
- data.tar.gz: af780a9538de5a69a5a1686d4b7b8c144f17d0939b6511dfc3912611d81734c43e143207724600d174c621fa70bd42eb6ed826383d44492169531f2346ae6fb1
6
+ metadata.gz: 399fa5e03d96661d9b1370b8d0be2709a6d9ca923532fceee1ed683df95f78452a4115c95a94d2685c198614f8b6a2e710a759043163f5333cac0c4040de45be
7
+ data.tar.gz: d2558a7df70f91d5dbd6db30afa2c7fece4c0d544d2686cc4782700560257348051a0eac3f3ee882943b7d791e4881272d3fb1c3b669ea3395b024e57b9ed833
@@ -0,0 +1,9 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ docker:
5
+ - image: circleci/ruby:2.5.1
6
+ steps:
7
+ - checkout
8
+ - run: bundle install
9
+ - run: rake
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. Custom domain support is a planned feature.
21
+ domains.
22
22
 
23
- This gem currently supports Ruby on Rails applications
24
- using the Selenium Firefox and Chrome drivers.
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 yourself as:
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(:suite) do
61
- Capybara::Webmock.start
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 checking out the repo, run `bin/setup` to install dependencies. Then, run
115
- `rake spec` to run the tests. You can also run `bin/console` for an interactive
116
- prompt that will allow you to experiment.
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 this gem onto your local machine, run `bundle exec rake install`. To
119
- release a new version, update the version number in `version.rb`, and then run
120
- `bundle exec rake release`, which will create a git tag for the version, push
121
- git commits and tags, and push the `.gem` file to
122
- [rubygems.org](https://rubygems.org).
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
 
@@ -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
- log_file = File.join('log', 'test.log')
14
- gem_path = File.dirname(__FILE__)
15
- proxy_file = File.join(gem_path, 'webmock', 'config.ru')
16
- IO.popen("PROXY_PORT_NUMBER=#{port_number} rackup #{proxy_file} >> #{log_file} 2>&1")
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 stop
20
- if File.exist?(Capybara::Webmock::Proxy::PID_FILE)
21
- rack_pid = File.read(Capybara::Webmock::Proxy::PID_FILE).to_i
22
- Process.kill('HUP', rack_pid)
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
- ::Selenium::WebDriver::Chrome::Options.new.tap do |options|
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, options: Capybara::Webmock.chrome_options)
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
- PID_FILE = File.join('tmp', 'pids', 'capybara_webmock_proxy.pid')
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 allowed_url?(allowed_urls, request.host)
15
+ if allowed_host?(request.host)
22
16
  super(env)
23
17
  else
24
- ['200', {'Content-Type' => 'text/html'}, ['']]
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 allowed_url?(urls, host)
41
- case urls
42
- when Array
43
- urls.any? { |url| allowed_url?(url, host) }
44
- when Regexp
45
- urls =~ host
46
- when String
47
- urls == host
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
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Webmock
3
- VERSION = '0.4.4'
3
+ VERSION = '0.5.0'.freeze
4
4
  end
5
5
  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.4
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-06-27 00:00:00.000000000 Z
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