Skip to content

Commit fb33f13

Browse files
committed
initial open-source commit
0 parents  commit fb33f13

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1877
-0
lines changed

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.bundle/
2+
log/*.log
3+
pkg/
4+
spec/examples.txt
5+
spec/dummy/log
6+
spec/dummy/db/*.sqlite3
7+
doc/
8+
.yardoc/
9+
Gemfile.lock

.rspec

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--tty
2+
--color
3+
--require spec_helper

.ruby-version

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2.3.1

.travis.yml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
language: ruby
2+
rvm:
3+
- 2.3.1
4+
- jruby-9.1.5.0
5+
before_install:
6+
- gem update --system
7+
- gem update bundler
8+
- gem cleanup bundler
9+
install: "bundle install --jobs 8"

Gemfile

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
source 'https://rubygems.org'
2+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
3+
4+
gemspec
5+
6+
platform :jruby do
7+
github 'jruby/activerecord-jdbc-adapter', branch: 'rails-5' do
8+
gem 'activerecord-jdbcsqlite3-adapter'
9+
end
10+
gem 'jdbc-sqlite3'
11+
end
12+
13+
gem 'sqlite3', '~> 1.3.10', platforms: :ruby

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Betterment
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9+
of the Software, and to permit persons to whom the Software is furnished to do
10+
so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
WebValve
2+
========
3+
4+
[![Build Status](https://travis-ci.com/Betterment/webvalve.svg?token=6b6DErRMUHX47kEoBZ3t&branch=master)](https://travis-ci.com/Betterment/webvalve)
5+
6+
WebValve is a tool for defining and registering fake implementations of
7+
HTTP services and toggling between the real services and the fake ones
8+
in non-production environments.
9+
10+
This library is made possible by the incredible gems
11+
[WebMock](https://github.com/bblimke/webmock) and
12+
[Sinatra](https://github.com/sinatra/sinatra).
13+
14+
## Getting Started
15+
16+
### Network connections disabled by default
17+
18+
The default mode in development and test is to disallow all HTTP network
19+
connections. This provides a clean foundation for consuming new
20+
services. If you add a new service integration, the first thing that you
21+
will be presented with when you attempt to hit it in development or test
22+
is a warning that the requested URL was not mocked. This behavior comes
23+
straight outta WebMock.
24+
25+
```ruby
26+
irb(main):007:0> Net::HTTP.get(URI('http://bank.dev'))
27+
28+
WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: GET http://bank.dev/ with headers {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}
29+
30+
You can stub this request with the following snippet:
31+
32+
stub_request(:get, "http://bank.dev/").
33+
with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
34+
to_return(:status => 200, :body => "", :headers => {})
35+
36+
============================================================
37+
```
38+
39+
### Creating a config file
40+
41+
The first thing to do is run the install generator.
42+
43+
```
44+
$ rails generate webvalve:install
45+
```
46+
47+
This will drop a new file in your config directory.
48+
49+
```ruby
50+
# config/webvalve.rb
51+
52+
# # register services
53+
#
54+
# WebValve.register FakeBank
55+
# WebValve.register FakeExample, url: 'https://api.example.org'
56+
#
57+
# # whitelist urls
58+
#
59+
# WebValve.whitelist_url 'https://example.com'
60+
```
61+
62+
### Registering a service
63+
64+
Next, you will want create a `FakeService` and register
65+
it with the framework.
66+
67+
This can be accomplished by running the fake service generator:
68+
69+
```
70+
$ rails generate webvalve:fake_service Bank
71+
```
72+
73+
This will generate a file `fake_bank.rb` in the top-level folder
74+
`webvalve`. This file will be autoloaded by Rails, so you can
75+
tweak it as you go without having to restart your application.
76+
77+
```ruby
78+
# webvalve/fake_bank.rb
79+
80+
class FakeBank < WebValve::FakeService
81+
# # define your routes here
82+
#
83+
# get '/widgets' do
84+
# json result: 'it works!'
85+
# end
86+
#
87+
# # toggle this service on via ENV
88+
#
89+
# export BANK_ENABLED=true
90+
end
91+
```
92+
93+
And it will automatically register it in `config/webvalve.rb`
94+
95+
```ruby
96+
# config/webvalve.rb
97+
WebValve.register FakeBank
98+
```
99+
100+
You'll also want to define an environment variable for the base url of
101+
your service.
102+
103+
```bash
104+
export BANK_API_URL='http://bank.dev'
105+
```
106+
107+
That's it. Now when you hit your service again, it will route your
108+
request into the `FakeBank` instance.
109+
110+
If you want to connect to the _actual_ service, all you have to do is
111+
set another environment variable.
112+
113+
```bash
114+
export BANK_ENABLED=true
115+
```
116+
117+
You will have to restart your application after making this change
118+
because service faking is an initialization time concern and not a
119+
runtime concern.
120+
121+
## Configuring fakes in tests
122+
123+
In order to get WebValve fake servies working properly in tests, you
124+
have to configure WebValve at the beginning of each test. For RSpec, there
125+
is a configuration provided.
126+
127+
```ruby
128+
# spec/rails_helper.rb
129+
require 'webvalve/rspec'
130+
```
131+
132+
For any other test framework, you will just want to set up a hook before
133+
each test that will run `WebValve.setup`.
134+
135+
## Setting deterministic fake results in tests
136+
137+
Given a scenario where we want to mock a specific behavior for an
138+
endpoint in a test, we can just use WebMock™.
139+
140+
```ruby
141+
# in an rspec test...
142+
143+
it 'handles 404s by returning nil' do
144+
fake_req = stub_request('http://bank.dev/some/url/1234')
145+
.to_return(status: 404, body: nil)
146+
147+
response = Faraday.get 'http://bank.dev/some/url/1234'
148+
expect(response.body).to be_nil
149+
expect(fake_req).to have_been_requested
150+
end
151+
```
152+
153+
In other scenarios where we don't care about the specific response from
154+
the endpoint, you can just lean into the behavior you've configured for
155+
that route in your fake service.
156+
157+
## Overriding conventional defaults
158+
159+
Sometimes a service integration may want to use an unconventional name
160+
for its environment variables. In that case, you can register the fake
161+
service using the optional `url:` argument.
162+
163+
```ruby
164+
# config/webvalve.rb
165+
166+
# using an ENV variable
167+
WebValve.register FakeBank, url: ENV.fetch("SOME_CUSTOM_API_URL")
168+
169+
# or with a constant value
170+
WebValve.register FakeBank, url: "https://some-service.com"
171+
```
172+
173+
## What's in a `FakeService`?
174+
175+
The definition of `FakeService` is really simple. It's just a
176+
`Sinatra::Base` class. It is wired up to support returning JSON
177+
responses and it will raise when a route is requested but it is
178+
not registered.
179+
180+
## How to Contribute
181+
182+
We would love for you to contribute! Anything that benefits the majority
183+
of `webvalve` users—from a documentation fix to an entirely new
184+
feature—is encouraged.
185+
186+
Before diving in, [check our issue
187+
tracker](//github.com/Betterment/webvalve/issues) and consider
188+
creating a new issue to get early feedback on your proposed change.
189+
190+
### Suggested Workflow
191+
192+
* Fork the project and create a new branch for your contribution.
193+
* Write your contribution (and any applicable test coverage).
194+
* Make sure all tests pass (`bundle exec rake`).
195+
* Submit a pull request.

Rakefile

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
begin
2+
require 'bundler/setup'
3+
rescue LoadError
4+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5+
end
6+
7+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
8+
load 'rails/tasks/engine.rake'
9+
10+
Bundler::GemHelper.install_tasks
11+
12+
if Rails.env.development? || Rails.env.test?
13+
if defined? Dummy
14+
require 'rspec/core'
15+
require 'rspec/core/rake_task'
16+
RSpec::Core::RakeTask.new(:spec)
17+
task default: :spec
18+
end
19+
end
20+
21+
require 'yard'
22+
YARD::Rake::YardocTask.new

bin/bundler

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'bundler' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('bundler', 'bundler')

bin/pry

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'pry' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('pry', 'pry')

bin/rails

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'rails' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('railties', 'rails')

bin/rake

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'rake' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('rake', 'rake')

bin/rspec

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'rspec' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('rspec-core', 'rspec')

bin/yard

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'yard' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('yard', 'yard')

bin/yardoc

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env ruby
2+
#
3+
# This file was generated by Bundler.
4+
#
5+
# The application 'yardoc' is installed as part of a gem, and
6+
# this file is here to facilitate running it.
7+
#
8+
9+
require 'pathname'
10+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11+
Pathname.new(__FILE__).realpath)
12+
13+
require 'rubygems'
14+
require 'bundler/setup'
15+
16+
load Gem.bin_path('yard', 'yardoc')

0 commit comments

Comments
 (0)