Skip to content

Commit

Permalink
Before handle request method (#273)
Browse files Browse the repository at this point in the history
* Support before_handle_request

* Support before_handle_request, fix proc usage

* Support before_handle_request, fix doc

* Fix test suite
  • Loading branch information
le0pard authored and ronwsmith committed Oct 27, 2019
1 parent f915f8e commit c6cfc3b
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 36 deletions.
45 changes: 29 additions & 16 deletions .travis.yml
@@ -1,23 +1,36 @@
language: ruby
cache: bundler
before_install:
- gem install bundler -v '< 2'
- export PHANTOMJS_VERSION='2.1.1'
- export PHANTOMJS_URL='https://github.com/Medium/phantomjs'
- export PHANTOMJS_URL+="/releases/download/v${PHANTOMJS_VERSION}"
- export PHANTOMJS_URL+="/phantomjs-${PHANTOMJS_VERSION}-linux-x86_64.tar.bz2"
- >
wget -q ${PHANTOMJS_URL} &&
tar xfv phantomjs-${PHANTOMJS_VERSION}-linux-x86_64.tar.bz2 \
--wildcards */bin/phantomjs --strip-components=2
- export PATH="`pwd`:${PATH}"
before_script:
- phantomjs --version
- bundle --version

rvm:
- 2.3
- 2.4
- 2.5
- 2.6
script: bundle exec rspec spec

cache:
bundler: true
directories:
- $HOME/.webdrivers

addons:
chrome: stable
apt:
update: true

sudo: false
dist: xenial

rvm:
- 2.3
- 2.4
- 2.5
- 2.6

matrix:
fast_finish: true

bundler_args: --jobs 3 --retry 3

before_install:
- gem update --system
- gem install bundler

15 changes: 12 additions & 3 deletions README.md
Expand Up @@ -436,9 +436,6 @@ internally on this request, or your test ended before it could complete successf

`c.after_cache_handles_request` is used to configure a callback that can operate on the response after it has been retrieved from the cache but before it is returned. The callback receives the request and response as arguments, with a request object like: `{ method: method, url: url, headers: headers, body: body }`. An example usage would be manipulating the Access-Control-Allow-Origin header so that your test server doesn't always have to run on the same port in order to accept cached responses to CORS requests:

`c.use_ignore_params` is used to choose whether to use the ignore_params blacklist or the allow_params whitelist. Set to `true` to use `c.ignore_params`,
`false` to use `c.allow_params`

```
Billy.configure do |c|
...
Expand All @@ -456,6 +453,18 @@ Billy.configure do |c|
end
```

`c.use_ignore_params` is used to choose whether to use the ignore_params blacklist or the allow_params whitelist. Set to `true` to use `c.ignore_params`,
`false` to use `c.allow_params`

`c.before_handle_request` is used to modify `method`, `url`, `headers`, `body` before handle request by `stubs`, `cache` or `proxy`. Method accept 4 argumens and must return array of this arguments:

```
c.before_handle_request = proc { |method, url, headers, body|
filtered_body = JSON.dump(filter_secret_data(JSON.load(body)))
[method, url, headers, filtered_body]
}
```

`c.cache_simulates_network_delays` is used to add some delay before cache returns response. When set to `true`, cached requests will wait from configured delay time before responding. This allows to catch various race conditions in asynchronous front-end requests. The default is `false`.

`c.cache_simulates_network_delay_time` is used to configure time (in seconds) to wait until responding from cache. The default is `0.1`.
Expand Down
9 changes: 9 additions & 0 deletions Rakefile
@@ -1,2 +1,11 @@
#!/usr/bin/env rake
require 'bundler/gem_tasks'

begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
rescue LoadError
end

desc 'Run all tests'
task default: [:spec]
25 changes: 17 additions & 8 deletions lib/billy/browsers/capybara.rb
Expand Up @@ -60,19 +60,28 @@ def self.register_selenium_driver
options.add_argument("--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}")

::Capybara::Selenium::Driver.new(
app, browser: :chrome,
options: options
app,
browser: :chrome,
options: options,
clear_local_storage: true,
clear_session_storage: true
)
end

::Capybara.register_driver :selenium_chrome_headless_billy do |app|
options = Selenium::WebDriver::Chrome::Options.new(args: %w[headless disable-gpu no-sandbox
enable-features=NetworkService,NetworkServiceInProcess])
options.add_argument("--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}")
options = Selenium::WebDriver::Chrome::Options.new
options.headless!
options.add_argument('--enable-features=NetworkService,NetworkServiceInProcess')
options.add_argument("--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}")
options.add_argument('--disable-gpu') if Gem.win_platform?
options.add_argument('--no-sandbox') if ENV['CI']

::Capybara::Selenium::Driver.new(
app, browser: :chrome,
options: options
app,
browser: :chrome,
options: options,
clear_local_storage: true,
clear_session_storage: true
)
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/billy/browsers/watir.rb
Expand Up @@ -19,6 +19,7 @@ def initialize(name, args = {})
private

def configure_chrome(args)
args[:headless] = true
args[:switches] ||= []
args[:switches] += %W[--proxy-server=#{Billy.proxy.host}:#{Billy.proxy.port}]
args
Expand Down
3 changes: 2 additions & 1 deletion lib/billy/config.rb
Expand Up @@ -11,7 +11,7 @@ class Config
:non_whitelisted_requests_disabled, :cache_path, :certs_path, :proxy_host, :proxy_port, :proxied_request_inactivity_timeout,
:proxied_request_connect_timeout, :dynamic_jsonp, :dynamic_jsonp_keys, :dynamic_jsonp_callback_name, :merge_cached_responses_whitelist,
:strip_query_params, :proxied_request_host, :proxied_request_port, :cache_request_body_methods, :after_cache_handles_request,
:cache_simulates_network_delays, :cache_simulates_network_delay_time, :record_requests, :record_stub_requests, :use_ignore_params
:cache_simulates_network_delays, :cache_simulates_network_delay_time, :record_requests, :record_stub_requests, :use_ignore_params, :before_handle_request

def initialize
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
Expand Down Expand Up @@ -50,6 +50,7 @@ def reset
@record_requests = false
@record_stub_requests = false
@use_ignore_params = true
@before_handle_request = nil
end
end

Expand Down
4 changes: 4 additions & 0 deletions lib/billy/handlers/request_handler.rb
Expand Up @@ -17,6 +17,10 @@ def handlers
def handle_request(method, url, headers, body)
request = request_log.record(method, url, headers, body)

if Billy.config.before_handle_request
method, url, headers, body = Billy.config.before_handle_request.call(method, url, headers, body)
end

# Process the handlers by order of importance
[:stubs, :cache, :proxy].each do |key|
if (response = handlers[key].handle_request(method, url, headers, body))
Expand Down
6 changes: 2 additions & 4 deletions puffing-billy.gemspec
Expand Up @@ -18,18 +18,16 @@ Gem::Specification.new do |gem|
gem.add_development_dependency 'rspec'
gem.add_development_dependency 'thin'
gem.add_development_dependency 'faraday'
gem.add_development_dependency 'poltergeist'
gem.add_development_dependency 'apparition'
# selenium-webdriver 3.8 drops support for PhantomJS
gem.add_development_dependency 'selenium-webdriver', '<= 3.7.0'
gem.add_development_dependency 'capybara'
gem.add_development_dependency 'capybara-webkit', '~> 1.0'
gem.add_development_dependency 'selenium-webdriver'
gem.add_development_dependency 'rack'
gem.add_development_dependency 'guard'
gem.add_development_dependency 'rb-inotify'
gem.add_development_dependency 'pry'
gem.add_development_dependency 'cucumber'
gem.add_development_dependency 'watir', '~> 6.10.0'
gem.add_development_dependency 'webdrivers'
gem.add_runtime_dependency 'addressable', '~> 2.5'
gem.add_runtime_dependency 'eventmachine', '~> 1.2'
gem.add_runtime_dependency 'em-synchrony'
Expand Down
22 changes: 22 additions & 0 deletions spec/lib/billy/handlers/request_handler_spec.rb
Expand Up @@ -128,6 +128,28 @@
allow(stub_handler).to receive(:handle_request).and_raise("Any Stub Error")
expect(subject.handle_request(*args)).to eql(error: "Any Stub Error")
end

context 'before_handle_request activated' do
before do
handle_request = proc { |method, url, headers, body|
[method, url, headers, "#{body}_modified"]
}
allow(Billy::config).to receive(:before_handle_request).and_return(handle_request)
end

after do
allow(Billy::config).to receive(:before_handle_request).and_call_original
end

it 'modify request before handling' do
new_args = %w(get url headers body_modified)
expect(stub_handler).to receive(:handle_request).with(*new_args)
expect(cache_handler).to receive(:handle_request).with(*new_args).and_return('bar')
expect(proxy_handler).to_not receive(:handle_request)
expect(subject.handle_request(*args)).to eql 'bar'
expect(subject.requests).to eql([{status: :complete, handler: :cache, method: 'get', url: 'url', headers: 'headers', body: 'body'}])
end
end
end

describe '#stubs' do
Expand Down
14 changes: 10 additions & 4 deletions spec/spec_helper.rb
Expand Up @@ -6,11 +6,17 @@
require 'rack'
require 'logger'
require 'fileutils'
require 'webdrivers'

browser = Billy::Browsers::Watir.new :phantomjs
Capybara.app = Rack::Directory.new(File.expand_path('../../examples', __FILE__))
Capybara.server = :webrick
Capybara.javascript_driver = :poltergeist_billy
$stdout.puts `#{::Selenium::WebDriver::Chrome::Service.driver_path.call} --version` if ENV['CI']

browser = Billy::Browsers::Watir.new :chrome

Capybara.configure do |config|
config.app = Rack::Directory.new(File.expand_path('../../examples', __FILE__))
config.server = :webrick
config.javascript_driver = :selenium_chrome_headless_billy
end

Billy.configure do |config|
config.logger = Logger.new(File.expand_path('../../log/test.log', __FILE__))
Expand Down

0 comments on commit c6cfc3b

Please sign in to comment.