mountebank 0.0.1
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 +7 -0
- data/.env +2 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +129 -0
- data/Rakefile +13 -0
- data/lib/mountebank.rb +34 -0
- data/lib/mountebank/helper.rb +39 -0
- data/lib/mountebank/imposter.rb +132 -0
- data/lib/mountebank/network.rb +51 -0
- data/lib/mountebank/stub.rb +46 -0
- data/lib/mountebank/stub/http_response.rb +11 -0
- data/lib/mountebank/stub/https_response.rb +2 -0
- data/lib/mountebank/stub/predicate.rb +26 -0
- data/lib/mountebank/stub/proxy_response.rb +14 -0
- data/lib/mountebank/stub/response.rb +24 -0
- data/lib/mountebank/stub/tcp_response.rb +9 -0
- data/lib/mountebank/version.rb +3 -0
- data/mountebank.gemspec +28 -0
- data/spec/examples_spec.rb +72 -0
- data/spec/mountebank/helper_spec.rb +20 -0
- data/spec/mountebank/imposter_spec.rb +207 -0
- data/spec/mountebank/network_spec.rb +23 -0
- data/spec/mountebank/stub/http_response_spec.rb +15 -0
- data/spec/mountebank/stub/https_response_spec.rb +15 -0
- data/spec/mountebank/stub/predicate_spec.rb +24 -0
- data/spec/mountebank/stub/proxy_response_spec.rb +23 -0
- data/spec/mountebank/stub/response_spec.rb +34 -0
- data/spec/mountebank/stub/tcp_response_spec.rb +13 -0
- data/spec/mountebank/stub_spec.rb +61 -0
- data/spec/mountebank_spec.rb +35 -0
- data/spec/spec_helper.rb +17 -0
- metadata +188 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
class Mountebank::Stub
|
2
|
+
attr_reader :responses, :predicates
|
3
|
+
|
4
|
+
def initialize(data={})
|
5
|
+
set_attributes(data)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.create(responses=[], predicates=[])
|
9
|
+
data = {
|
10
|
+
:responses => responses,
|
11
|
+
:predicates => predicates
|
12
|
+
}
|
13
|
+
new(data)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_json(*args)
|
17
|
+
data = {}
|
18
|
+
data[:responses] = @responses unless @responses.empty?
|
19
|
+
data[:predicates] = @predicates unless @predicates.empty?
|
20
|
+
data.to_json(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def set_attributes(data={})
|
26
|
+
@responses, @predicates = [], []
|
27
|
+
|
28
|
+
if data[:responses]
|
29
|
+
data[:responses].each do |response|
|
30
|
+
unless response.is_a? Mountebank::Stub::Response
|
31
|
+
response = Mountebank::Stub::Response.new(response)
|
32
|
+
end
|
33
|
+
@responses << response
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if data[:predicates]
|
38
|
+
data[:predicates].each do |predicate|
|
39
|
+
unless predicate.is_a? Mountebank::Stub::Predicate
|
40
|
+
predicate = Mountebank::Stub::Predicate.new(predicate)
|
41
|
+
end
|
42
|
+
@predicates << predicate
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Mountebank::Stub::HttpResponse < Mountebank::Stub::Response
|
2
|
+
def self.create(statusCode=200, headers={}, body='')
|
3
|
+
payload = {}
|
4
|
+
payload[:statusCode] = statusCode
|
5
|
+
payload[:headers] = headers unless headers.empty?
|
6
|
+
payload[:body] = body unless body.empty?
|
7
|
+
|
8
|
+
data = {is: payload}
|
9
|
+
new(data)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Mountebank::Stub::Predicate
|
2
|
+
attr_accessor :equals, :deepEquals, :contains, :startsWith, :endsWith, :matches, :exists, :not, :or, :and, :inject, :caseSensitive, :except
|
3
|
+
|
4
|
+
VALID_OPERATORS = [
|
5
|
+
:equals, :deepEquals, :contains, :startsWith, :endsWith, :matches, :exists, :not,
|
6
|
+
:or, :and, :inject
|
7
|
+
]
|
8
|
+
|
9
|
+
def initialize(data={})
|
10
|
+
VALID_OPERATORS.each do |key|
|
11
|
+
send("#{key}=", data[key]) if data.key?(key)
|
12
|
+
end
|
13
|
+
@caseSensitive = data[:caseSensitive] || nil
|
14
|
+
@except = data[:except] || nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_json(*args)
|
18
|
+
data = {}
|
19
|
+
VALID_OPERATORS.each do |key|
|
20
|
+
data[key] = send("#{key}") if instance_variable_defined?("@#{key}")
|
21
|
+
end
|
22
|
+
data[:caseSensitive] = @caseSensitive unless @caseSensitive.nil?
|
23
|
+
data[:except] = @except unless @except.nil?
|
24
|
+
data.to_json(*args)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Mountebank::Stub::ProxyResponse < Mountebank::Stub::Response
|
2
|
+
PROXY_MODE_ONCE = 'proxyOnce'
|
3
|
+
PROXY_MODE_ALWAYS = 'proxyAlways'
|
4
|
+
|
5
|
+
def self.create(to, mode=PROXY_MODE_ONCE, predicateGenerators=[])
|
6
|
+
data = {proxy: {
|
7
|
+
to: to,
|
8
|
+
mode: mode,
|
9
|
+
predicateGenerators: predicateGenerators
|
10
|
+
}
|
11
|
+
}
|
12
|
+
new(data)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Mountebank::Stub::Response
|
2
|
+
attr_accessor :is, :proxy, :inject
|
3
|
+
|
4
|
+
def initialize(data={})
|
5
|
+
@is = data[:is] || nil
|
6
|
+
@proxy = data[:proxy] || nil
|
7
|
+
@inject = data[:inject] || nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.with_injection(injection='')
|
11
|
+
return false if injection.empty?
|
12
|
+
|
13
|
+
data = {inject:injection}
|
14
|
+
new(data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_json(*args)
|
18
|
+
data = {}
|
19
|
+
data[:is] = @is unless @is.nil?
|
20
|
+
data[:proxy] = @proxy unless @proxy.nil?
|
21
|
+
data[:inject] = @inject unless @inject.nil?
|
22
|
+
data.to_json(*args)
|
23
|
+
end
|
24
|
+
end
|
data/mountebank.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mountebank/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mountebank"
|
8
|
+
spec.version = Mountebank::VERSION
|
9
|
+
spec.authors = ["Michael Cheng"]
|
10
|
+
spec.email = ["mcheng.work@gmail.com"]
|
11
|
+
spec.summary = %q{Ruby GEM to manage a Mountebank Test Server}
|
12
|
+
spec.description = %q{A simple Ruby library that lets you manage your Mountebank test server.}
|
13
|
+
spec.homepage = "https://github.com/CoderKungfu/mountebank-gem"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "faraday", "~>0.9.0"
|
22
|
+
spec.add_runtime_dependency "faraday_middleware"
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "dotenv", "~> 1.0.0"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'Examples' do
|
4
|
+
before:each do
|
5
|
+
reset_mountebank
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'get all imposters' do
|
9
|
+
it 'should be empty' do
|
10
|
+
expect(Mountebank.imposters).to be_empty
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'create imposter' do
|
15
|
+
it 'should create' do
|
16
|
+
port = 4545
|
17
|
+
protocol = Mountebank::Imposter::PROTOCOL_HTTP
|
18
|
+
imposter = Mountebank::Imposter.create(port, protocol)
|
19
|
+
|
20
|
+
expect(imposter.reload.requests).to be_empty
|
21
|
+
test_url('http://127.0.0.1:4545')
|
22
|
+
expect(imposter.reload.requests).to_not be_empty
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'create imposter with stub' do
|
27
|
+
it 'should have stub' do
|
28
|
+
port = 4545
|
29
|
+
protocol = Mountebank::Imposter::PROTOCOL_HTTP
|
30
|
+
imposter = Mountebank::Imposter.build(port, protocol)
|
31
|
+
|
32
|
+
# Create a response
|
33
|
+
status_code = 200
|
34
|
+
headers = {"Content-Type" => "application/json"}
|
35
|
+
body = {foo:"bar"}.to_json
|
36
|
+
response = Mountebank::Stub::HttpResponse.create(status_code, headers, body)
|
37
|
+
|
38
|
+
imposter.add_stub(response)
|
39
|
+
imposter.save!
|
40
|
+
|
41
|
+
expect(imposter.reload.requests).to be_empty
|
42
|
+
expect(test_url('http://127.0.0.1:4545')).to eq('{"foo":"bar"}')
|
43
|
+
expect(imposter.reload.requests).to_not be_empty
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'create imposter with stub & predicate' do
|
48
|
+
it 'should have stub & predicate' do
|
49
|
+
port = 4545
|
50
|
+
protocol = Mountebank::Imposter::PROTOCOL_HTTP
|
51
|
+
imposter = Mountebank::Imposter.build(port, protocol)
|
52
|
+
|
53
|
+
# Create a response
|
54
|
+
status_code = 200
|
55
|
+
headers = {"Content-Type" => "application/json"}
|
56
|
+
body = {foo:"bar2"}.to_json
|
57
|
+
response = Mountebank::Stub::HttpResponse.create(status_code, headers, body)
|
58
|
+
|
59
|
+
# Create a predicate
|
60
|
+
data = {equals: {path:"/test"}}
|
61
|
+
predicate = Mountebank::Stub::Predicate.new(data)
|
62
|
+
|
63
|
+
imposter.add_stub(response, predicate)
|
64
|
+
imposter.save!
|
65
|
+
|
66
|
+
expect(imposter.reload.requests).to be_empty
|
67
|
+
expect(test_url('http://127.0.0.1:4545/test')).to eq('{"foo":"bar2"}')
|
68
|
+
expect(test_url('http://127.0.0.1:4545')).to eq('')
|
69
|
+
expect(imposter.reload.requests).to_not be_empty
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Mountebank::Helper do
|
4
|
+
describe '.symbolize' do
|
5
|
+
let(:hash) { {
|
6
|
+
"foo" => {"bar" => "Baz"},
|
7
|
+
"goo" => "balls"
|
8
|
+
}
|
9
|
+
}
|
10
|
+
let(:expected_hash) { {
|
11
|
+
:foo => {:bar => "Baz"},
|
12
|
+
:goo => "balls"
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
it 'symbolizes' do
|
17
|
+
expect(Mountebank::Helper.symbolize(hash)).to eq expected_hash
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Mountebank::Imposter do
|
4
|
+
before:each do
|
5
|
+
reset_mountebank
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:port) { 4545 }
|
9
|
+
let(:protocol) { Mountebank::Imposter::PROTOCOL_HTTP }
|
10
|
+
|
11
|
+
shared_examples 'blank imposter' do
|
12
|
+
it 'valid imposter' do
|
13
|
+
expect(imposter).to be_a Mountebank::Imposter
|
14
|
+
expect(imposter.port).to eq port
|
15
|
+
expect(imposter.protocol).to eq protocol
|
16
|
+
expect(imposter.name).to eq "imposter_#{port}"
|
17
|
+
expect(imposter.stubs).to be_empty
|
18
|
+
expect(imposter.requests).to be_empty
|
19
|
+
expect(imposter.mode).to be_nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
shared_examples 'persists imposter' do
|
24
|
+
it 'persist to server' do
|
25
|
+
imposter
|
26
|
+
expect(Mountebank.imposters).to_not be_empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.build' do
|
31
|
+
let(:imposter) { Mountebank::Imposter.build(port, protocol) }
|
32
|
+
|
33
|
+
it_should_behave_like 'blank imposter'
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.create' do
|
37
|
+
context 'new imposter' do
|
38
|
+
let(:imposter) { Mountebank::Imposter.create(port, protocol) }
|
39
|
+
|
40
|
+
it_should_behave_like 'blank imposter'
|
41
|
+
it_should_behave_like 'persists imposter'
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'assumes 2nd argument to be `http`' do
|
45
|
+
let(:imposter) { Mountebank::Imposter.create(port) }
|
46
|
+
|
47
|
+
it_should_behave_like 'blank imposter'
|
48
|
+
it_should_behave_like 'persists imposter'
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'other creation options' do
|
52
|
+
let(:imposter) { Mountebank::Imposter.create(port, protocol, name:'meow_server') }
|
53
|
+
|
54
|
+
it 'uses a different name' do
|
55
|
+
expect(imposter.name).to eq 'meow_server'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'invalid arguments' do
|
60
|
+
it 'raises invalid port' do
|
61
|
+
expect{ Mountebank::Imposter.create('abcd') }.to raise_error 'Invalid port number'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'raises invalid protocol' do
|
65
|
+
expect{ Mountebank::Imposter.create(port, 'seattle') }.to raise_error 'Invalid protocol'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'creates stub response' do
|
70
|
+
let(:responses) { [
|
71
|
+
{is: {statusCode: 200, body:"ohai"}}
|
72
|
+
]
|
73
|
+
}
|
74
|
+
let(:predicates) { [] }
|
75
|
+
let(:stubs) { [
|
76
|
+
Mountebank::Stub.create(responses, predicates)
|
77
|
+
]
|
78
|
+
}
|
79
|
+
let!(:imposter) { Mountebank::Imposter.create(port, protocol, stubs:stubs) }
|
80
|
+
|
81
|
+
it 'is valid' do
|
82
|
+
expect(test_url('http://127.0.0.1:4545')).to eq 'ohai'
|
83
|
+
expect(imposter.reload.requests).to_not be_empty
|
84
|
+
expect(imposter.stubs.first).to be_a Mountebank::Stub
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with predicates' do
|
88
|
+
let(:response_body) { "Its a real test" }
|
89
|
+
let(:responses) { [
|
90
|
+
{is: {statusCode: 200, body:response_body}}
|
91
|
+
]
|
92
|
+
}
|
93
|
+
let(:predicates) { [
|
94
|
+
{equals: {path:'/test'}}
|
95
|
+
]
|
96
|
+
}
|
97
|
+
|
98
|
+
it 'is valid' do
|
99
|
+
expect(test_url('http://127.0.0.1:4545/test')).to eq response_body
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '.get' do
|
106
|
+
before do
|
107
|
+
Mountebank::Imposter.create(port)
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'valid imposter' do
|
111
|
+
let(:imposter) { Mountebank::Imposter.find(port) }
|
112
|
+
|
113
|
+
it_should_behave_like 'blank imposter'
|
114
|
+
it_should_behave_like 'persists imposter'
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'unknown imposter' do
|
118
|
+
it 'returns false' do
|
119
|
+
expect(Mountebank::Imposter.find(4546)).to_not be
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '.delete' do
|
125
|
+
before do
|
126
|
+
Mountebank::Imposter.create(port)
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'has imposter' do
|
130
|
+
it 'returns true' do
|
131
|
+
expect(Mountebank::Imposter.delete(port)).to be
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'no imposter' do
|
136
|
+
it 'returns false' do
|
137
|
+
expect(Mountebank::Imposter.delete(4546)).to_not be
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#reload' do
|
143
|
+
before do
|
144
|
+
Mountebank::Imposter.create(port)
|
145
|
+
end
|
146
|
+
|
147
|
+
let!(:imposter) { Mountebank::Imposter.find(port) }
|
148
|
+
|
149
|
+
context 'no change' do
|
150
|
+
it 'returns imposter' do
|
151
|
+
expect(imposter.reload).to be_a Mountebank::Imposter
|
152
|
+
end
|
153
|
+
|
154
|
+
it_should_behave_like 'blank imposter'
|
155
|
+
it_should_behave_like 'persists imposter'
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'has requests' do
|
159
|
+
it 'returns imposter with requests' do
|
160
|
+
test_url('http://127.0.0.1:4545')
|
161
|
+
expect(imposter.reload.requests).to_not be_empty
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#add_stub' do
|
167
|
+
let(:imposter) { Mountebank::Imposter.build(port, protocol) }
|
168
|
+
|
169
|
+
context 'with response' do
|
170
|
+
before do
|
171
|
+
response = Mountebank::Stub::HttpResponse.create(200, {}, 'ohai you')
|
172
|
+
imposter.add_stub(response)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'adds new stub' do
|
176
|
+
expect(imposter.to_json).to eq("{\"port\":#{port},\"protocol\":\"#{protocol}\",\"name\":\"imposter_#{port}\",\"stubs\":[{\"responses\":[{\"is\":{\"statusCode\":200,\"body\":\"ohai you\"}}]}]}")
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'is valid imposter' do
|
180
|
+
imposter.save!
|
181
|
+
expect(test_url('http://127.0.0.1:4545')).to eq('ohai you')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'with predicate' do
|
186
|
+
before do
|
187
|
+
response = Mountebank::Stub::HttpResponse.create(200, {}, 'ohai test2')
|
188
|
+
data = {equals: {path:'/test2'}}
|
189
|
+
predicate = Mountebank::Stub::Predicate.new(data)
|
190
|
+
imposter.add_stub(response, predicate)
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'is valid imposter' do
|
194
|
+
imposter.save!
|
195
|
+
expect(test_url('http://127.0.0.1:4545/test2')).to eq('ohai test2')
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe '#replayable_data' do
|
201
|
+
let(:imposter) { Mountebank::Imposter.build(port, protocol) }
|
202
|
+
|
203
|
+
it 'returns valid data' do
|
204
|
+
expect(imposter.replayable_data).to eq({port:port, protocol:protocol, name:"imposter_#{port}"})
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|