Skip to content

Commit

Permalink
change WebValve.register to accept a class name instead of class (#35)
Browse files Browse the repository at this point in the history
* change WebValve.register to accept a class name instead of class

rails 6 autoloading emits a deprecation warning for class loading during
app initialization. webvalve's register call is a culprit here, but it
doesn't have to be. this changeset makes it so that webvalve accepts a
stringified class name instead of a class and makes that all work
properly with the internals.

* update and correct changelog

* fix CI, update version and fix changelog

* add 2.6.1
  • Loading branch information
samandmoore authored Sep 22, 2019
1 parent ad2896c commit 03a16d0
Show file tree
Hide file tree
Showing 19 changed files with 88 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.3.1
2.6.1
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ language: ruby
rvm:
- 2.3.1
- 2.4.2
- 2.5.1
- 2.6.1
gemfile:
- gemfiles/rails_5_0.gemfile
- gemfiles/rails_5_1.gemfile
- gemfiles/rails_5_2.gemfile
- gemfiles/rails_6_0.gemfile
- gemfiles/ruby.gemfile
before_install:
- gem update --system
- gem update bundler
- gem pristine bundler
- gem cleanup bundler
install: "bundle install --jobs 8"
matrix:
exclude:
- rvm: 2.3.1
gemfile: gemfiles/rails_6_0.gemfile
- rvm: 2.4.2
gemfile: gemfiles/rails_6_0.gemfile
8 changes: 8 additions & 0 deletions Appraisals
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@ appraise 'rails-5-1' do
gem 'rails', '~> 5.1.0'
end

appraise 'rails-5-2' do
gem 'rails', '~> 5.2.0'
end

appraise 'rails-6-0' do
gem 'rails', '~> 6.0.0'
end

appraise 'ruby' do
end
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ and this project aims to adhere to [Semantic Versioning](http://semver.org/spec/
### Added
### Removed

## [0.10.0] - 2019-09-23
### Changed
- `Webvalve.register` no longer accepts classes; you must provide class names as strings. Fixes a Rails 6 deprecation warning. (https://github.com/Betterment/webvalve/pull/35)

## [0.9.10] - 2019-09-09
### Changed
- rename `whitelist_url` to `allow_url` (https://github.com/Betterment/retail/pull/4424)
- rename `whitelist_url` to `allow_url` (https://github.com/Betterment/webvalve/pull/33)

## [0.9.9] - 2019-05-24
### Changed
Expand All @@ -34,7 +38,8 @@ and this project aims to adhere to [Semantic Versioning](http://semver.org/spec/
### Changed
- WebMock 3+ support from @messanjah (https://github.com/Betterment/webvalve/pull/22)

[Unreleased]: https://github.com/Betterment/webvalve/compare/v0.9.9...HEAD
[Unreleased]: https://github.com/Betterment/webvalve/compare/v0.10.0...HEAD
[0.10.0]: https://github.com/Betterment/webvalve/compare/v0.9.10...v0.10.0
[0.9.10]: https://github.com/Betterment/webvalve/compare/v0.9.9...v0.9.10
[0.9.9]: https://github.com/Betterment/webvalve/compare/v0.9.8...v0.9.9
[0.9.8]: https://github.com/Betterment/webvalve/compare/v0.9.7...v0.9.8
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ is a warning that the requested URL was not mocked. This behavior comes
straight outta WebMock.

```ruby
irb(main):007:0> Net::HTTP.get(URI('http://bank.dev'))
irb(main):007:0> Net::HTTP.get(URI('http://bank.test'))

WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://bank.dev/ with headers {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}
WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://bank.test/ with headers {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}

You can stub this request with the following snippet:

stub_request(:get, "http://bank.dev/").
stub_request(:get, "http://bank.test/").
with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
to_return(:status => 200, :body => "", :headers => {})

Expand All @@ -68,12 +68,12 @@ This will drop a new file in your config directory.

# # register services
#
# WebValve.register FakeBank
# WebValve.register FakeExample, url: 'https://api.example.org'
# WebValve.register "FakeBank"
# WebValve.register "FakeExample", url: "https://api.example.org"
#
# # add urls to allowlist
#
# WebValve.allow_url 'https://example.com'
# WebValve.allow_url "https://example.com"
```

If you're not using Rails, you can create this file for yourself.
Expand Down Expand Up @@ -113,7 +113,7 @@ And it will automatically register it in `config/webvalve.rb`

```ruby
# config/webvalve.rb
WebValve.register FakeBank
WebValve.register "FakeBank"
```

Again, if you're not using Rails, you'll have to create this file
Expand All @@ -123,7 +123,7 @@ You'll also want to define an environment variable for the base url of
your service.

```bash
export BANK_API_URL='http://bank.dev'
export BANK_API_URL='http://bank.test'
```

That's it. Now when you hit your service again, it will route your
Expand Down Expand Up @@ -189,10 +189,10 @@ endpoint in a test, we can just use WebMock™.
# in an rspec test...

it 'handles 404s by returning nil' do
fake_req = stub_request('http://bank.dev/some/url/1234')
fake_req = stub_request('http://bank.test/some/url/1234')
.to_return(status: 404, body: nil)

response = Faraday.get 'http://bank.dev/some/url/1234'
response = Faraday.get 'http://bank.test/some/url/1234'
expect(response.body).to be_nil
expect(fake_req).to have_been_requested
end
Expand Down
2 changes: 1 addition & 1 deletion examples/sinatra/config/webvalve.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'webvalve'
require_relative '../webvalve/fake_twitter'

WebValve.register FakeTwitter, url: FakeTwitter::URL
WebValve.register 'FakeTwitter', url: 'http://faketwitter.test'
2 changes: 0 additions & 2 deletions examples/sinatra/webvalve/fake_twitter.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
class FakeTwitter < WebValve::FakeService
URL = 'http://faketwitter.test'.freeze

get '/' do
json hello: 'world'
end
Expand Down
7 changes: 7 additions & 0 deletions gemfiles/rails_5_2.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "rails", "~> 5.2.0"

gemspec path: "../"
7 changes: 7 additions & 0 deletions gemfiles/rails_6_0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file was generated by Appraisal

source "https://rubygems.org"

gem "rails", "~> 6.0.0"

gemspec path: "../"
2 changes: 1 addition & 1 deletion lib/generators/webvalve/fake_service_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class #{fake_service_class_name} < WebValve::FakeService

def register_fake_in_config
append_to_file config_file_path do <<~RUBY
WebValve.register #{fake_service_class_name}
WebValve.register "#{fake_service_class_name}"
RUBY
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/generators/webvalve/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ def create_config_file
create_file full_file_path, <<-FILE.strip_heredoc
# # register services
#
# WebValve.register FakeThing
# WebValve.register FakeExample, url: 'https://api.example.org'
# WebValve.register "FakeThing"
# WebValve.register "FakeExample", url: "https://api.example.org"
#
# # add urls to the allowlist
#
# WebValve.allow_url 'https://example.com'
# WebValve.allow_url "https://example.com"
FILE
end

Expand Down
12 changes: 6 additions & 6 deletions lib/webvalve/fake_service_config.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module WebValve
class FakeServiceConfig
attr_reader :service
attr_reader :service_class_name

def initialize(service:, url: nil)
@service = service
def initialize(service_class_name:, url: nil)
@service_class_name = service_class_name
@custom_service_url = url
end

Expand All @@ -26,9 +26,9 @@ def service_url

def missing_url_message
<<~MESSAGE
There is no URL defined for #{service.name}.
There is no URL defined for #{service_class_name}.
Configure one by setting the ENV variable "#{service_name.to_s.upcase}_API_URL"
or by using WebValve.register #{service.name}, url: "http://something.dev"
or by using WebValve.register "#{service_class_name}", url: "http://something.dev"
MESSAGE
end

Expand All @@ -45,7 +45,7 @@ def default_service_url
end

def service_name
@service_name ||= service.name.demodulize.underscore.sub 'fake_', ''
@service_name ||= service_class_name.demodulize.underscore.sub 'fake_', ''
end
end
end
6 changes: 3 additions & 3 deletions lib/webvalve/fake_service_wrapper.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module WebValve
class FakeServiceWrapper
# lazily resolve the app constant to leverage rails class reloading
def initialize(app)
@app_klass_name = app.name
def initialize(app_class_name)
@app_class_name = app_class_name
end

def call(env)
Expand All @@ -12,7 +12,7 @@ def call(env)
private

def app
@app_klass_name.constantize
@app_class_name.constantize
end
end
end
9 changes: 5 additions & 4 deletions lib/webvalve/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ module WebValve
class Manager
include Singleton

def register(fake_service, **args)
raise "#{fake_service.inspect} already registered" if fake_service_configs.any? { |c| c.service == fake_service }
fake_service_configs << FakeServiceConfig.new(service: fake_service, **args)
def register(fake_service_class_name, **args)
raise "register must be called with a string to comply with Rails autoloading" unless fake_service_class_name.is_a?(String)
raise "#{fake_service_class_name.inspect} already registered" if fake_service_configs.any? { |c| c.service_class_name == fake_service_class_name }
fake_service_configs << FakeServiceConfig.new(service_class_name: fake_service_class_name, **args)
end

def allow_url(url)
Expand Down Expand Up @@ -62,7 +63,7 @@ def webmock_service(config)
WebMock.stub_request(
:any,
url_to_regexp(config.service_url)
).to_rack(FakeServiceWrapper.new(config.service))
).to_rack(FakeServiceWrapper.new(config.service_class_name))
end

def allowlist_service(config)
Expand Down
2 changes: 1 addition & 1 deletion lib/webvalve/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module WebValve
VERSION = "0.9.10"
VERSION = "0.10.0"
end
4 changes: 2 additions & 2 deletions spec/webvalve/fake_service_config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def self.name
stub_const('FakeDummy', fake_service)
end

subject { described_class.new service: fake_service }
subject { described_class.new service_class_name: fake_service.name }

describe '.should_intercept?' do
context 'in test env' do
Expand Down Expand Up @@ -136,7 +136,7 @@ def self.name
expect { subject.service_url }.to raise_error <<~MESSAGE
There is no URL defined for FakeDummy.
Configure one by setting the ENV variable "DUMMY_API_URL"
or by using WebValve.register FakeDummy, url: "http://something.dev"
or by using WebValve.register "FakeDummy", url: "http://something.dev"
MESSAGE
end

Expand Down
4 changes: 2 additions & 2 deletions spec/webvalve/fake_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def self.name

it 'raise a useful error when an unmapped route is requested' do
with_env 'DUMMY_API_URL' => 'http://dummy.dev' do
WebValve.register subject
WebValve.register subject.name
WebValve.setup

expect { Net::HTTP.get(URI('http://dummy.dev/foos')) }.to raise_error(RuntimeError, /route not defined for GET/)
Expand All @@ -37,7 +37,7 @@ def self.name

it 'returns the result from the fake when a mapped route is requested' do
with_env 'DUMMY_API_URL' => 'http://dummy.dev' do
WebValve.register subject
WebValve.register subject.name
WebValve.setup

expect(Net::HTTP.get(URI('http://dummy.dev/widgets'))).to eq({ result: 'it works!' }.to_json)
Expand Down
20 changes: 10 additions & 10 deletions spec/webvalve/manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,22 @@
end
end

describe '#register(fake_service)' do
describe '#register(fake_service_class_name)' do
it 'raises on duplicates' do
fake = class_double(WebValve::FakeService)
fake = class_double(WebValve::FakeService, name: "FooService")

subject.register fake
expect { subject.register fake }.to raise_error(/already registered/)
subject.register fake.name
expect { subject.register fake.name }.to raise_error(/already registered/)
expect(subject.fake_service_configs.count).to eq 1
expect(subject.fake_service_configs.first.service).to eq fake
expect(subject.fake_service_configs.first.service_class_name).to eq fake.name
end
end

describe '#register(fake_service, url:)' do
describe '#register(fake_service_class_name, url:)' do
it 'stores the url' do
fake = class_double(WebValve::FakeService)
fake = class_double(WebValve::FakeService, name: "FooService")

subject.register fake, url: 'http://manual.dev'
subject.register fake.name, url: 'http://manual.dev'
expect(subject.fake_service_configs.first.service_url).to eq 'http://manual.dev'
end
end
Expand Down Expand Up @@ -109,7 +109,7 @@
allow(WebMock).to receive(:stub_request).and_return(web_mock_stubble)

with_env 'SOMETHING_API_URL' => 'http://fake.dev' do
subject.register disabled_service
subject.register disabled_service.name
subject.setup
end

Expand All @@ -121,7 +121,7 @@
enabled_service = class_double(WebValve::FakeService, name: 'FakeSomething')

with_env 'SOMETHING_ENABLED' => '1', 'SOMETHING_API_URL' => 'http://real.dev' do
subject.register enabled_service
subject.register enabled_service.name
subject.setup
end

Expand Down
8 changes: 4 additions & 4 deletions webvalve.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ Gem::Specification.new do |s|
s.files = Dir["{lib}/**/*", "LICENSE", "Rakefile", "README.md", "CHANGELOG.md"]
s.test_files = Dir["spec/**/*"]

s.add_dependency 'activesupport', '>= 4.2'
s.add_dependency 'sinatra', '>= 1.4', '< 3'
s.add_dependency 'sinatra-contrib', '>= 1.4', '< 3'
s.add_dependency "activesupport", ">= 4.2"
s.add_dependency "sinatra", ">= 1.4", "< 3"
s.add_dependency "sinatra-contrib", ">= 1.4", "< 3"
s.add_dependency "webmock", ">= 2.0"

s.add_development_dependency 'appraisal', '~> 2.2.0'
s.add_development_dependency "appraisal", "~> 2.2.0"
s.add_development_dependency "rspec"
s.add_development_dependency "pry"
s.add_development_dependency "yard"
Expand Down

0 comments on commit 03a16d0

Please sign in to comment.