whisperer 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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +13 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +293 -0
- data/Rakefile +1 -0
- data/TODO.md +47 -0
- data/lib/whisperer.rb +102 -0
- data/lib/whisperer/config.rb +40 -0
- data/lib/whisperer/convertors/hash.rb +39 -0
- data/lib/whisperer/convertors/interaction.rb +21 -0
- data/lib/whisperer/dsl.rb +19 -0
- data/lib/whisperer/dsl/base.rb +47 -0
- data/lib/whisperer/dsl/body.rb +33 -0
- data/lib/whisperer/dsl/headers.rb +20 -0
- data/lib/whisperer/dsl/request.rb +15 -0
- data/lib/whisperer/dsl/response.rb +15 -0
- data/lib/whisperer/dsl/response/status.rb +10 -0
- data/lib/whisperer/generator.rb +43 -0
- data/lib/whisperer/helpers.rb +16 -0
- data/lib/whisperer/placeholder.rb +14 -0
- data/lib/whisperer/preprocessors.rb +19 -0
- data/lib/whisperer/preprocessors/base.rb +13 -0
- data/lib/whisperer/preprocessors/content_length.rb +17 -0
- data/lib/whisperer/preprocessors/response_body.rb +23 -0
- data/lib/whisperer/record.rb +48 -0
- data/lib/whisperer/record/body.rb +15 -0
- data/lib/whisperer/record/headers.rb +22 -0
- data/lib/whisperer/record/request.rb +16 -0
- data/lib/whisperer/record/response.rb +18 -0
- data/lib/whisperer/record/response/status.rb +10 -0
- data/lib/whisperer/samples/cassette_builder.rb +24 -0
- data/lib/whisperer/serializers/base.rb +24 -0
- data/lib/whisperer/serializers/json.rb +33 -0
- data/lib/whisperer/serializers/json_multiple.rb +14 -0
- data/lib/whisperer/tasks/whisperer.rake +88 -0
- data/lib/whisperer/version.rb +3 -0
- data/spec/cassette_builders/arya_stark.rb +26 -0
- data/spec/cassette_builders/bran_stark.rb +19 -0
- data/spec/cassette_builders/empty_robb_stark.rb +20 -0
- data/spec/cassette_builders/robb_stark.rb +30 -0
- data/spec/cassette_builders/robb_stark_without_content_length.rb +20 -0
- data/spec/cassette_builders/sansa_stark.rb +9 -0
- data/spec/cassette_builders/starks.rb +31 -0
- data/spec/cassette_builders/wolfs.rb +7 -0
- data/spec/cassettes/empty_robb_stark.yml +22 -0
- data/spec/cassettes/girls/arya_stark.yml +24 -0
- data/spec/cassettes/robb_stark.yml +28 -0
- data/spec/cassettes/robb_stark_without_content_length.yml +22 -0
- data/spec/cassettes/sansa_stark.yml +24 -0
- data/spec/cassettes/starks.yml +28 -0
- data/spec/cassettes/wolfs.yml +28 -0
- data/spec/factories/arya_stark.rb +7 -0
- data/spec/factories/bran_stark.rb +7 -0
- data/spec/factories/ned_stark.rb +7 -0
- data/spec/factories/robb_stark.rb +7 -0
- data/spec/factories/sansa_stark.rb +7 -0
- data/spec/integration/whisperer_spec.rb +51 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/spec_integration_helper.rb +6 -0
- data/spec/support/cassettes.rb +16 -0
- data/spec/support/custom_serializer.rb +5 -0
- data/spec/unit/config_spec.rb +94 -0
- data/spec/unit/convertors/hash_spec.rb +59 -0
- data/spec/unit/convertors/interaction_spec.rb +46 -0
- data/spec/unit/dsl/base_spec.rb +99 -0
- data/spec/unit/dsl/body_spec.rb +73 -0
- data/spec/unit/dsl/headers_spec.rb +31 -0
- data/spec/unit/dsl/request_spec.rb +4 -0
- data/spec/unit/dsl/response_spec.rb +4 -0
- data/spec/unit/dsl/status_spec.rb +4 -0
- data/spec/unit/dsl_spec.rb +4 -0
- data/spec/unit/generator_spec.rb +77 -0
- data/spec/unit/helpers_spec.rb +38 -0
- data/spec/unit/preprocessors/content_length_spec.rb +39 -0
- data/spec/unit/preprocessors/response_body_spec.rb +55 -0
- data/spec/unit/preprocessors_spec.rb +8 -0
- data/spec/unit/record/headers_spec.rb +21 -0
- data/spec/unit/record/response_spec.rb +11 -0
- data/spec/unit/record_spec.rb +77 -0
- data/spec/unit/serializers/base_spec.rb +19 -0
- data/spec/unit/serializers/json_multiple_spec.rb +24 -0
- data/spec/unit/serializers/json_spec.rb +37 -0
- data/spec/unit/whisperer_spec.rb +189 -0
- data/whisperer.gemspec +28 -0
- metadata +277 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NDliMDRjMTM4ZDRiMDMyZDIwMTc1Y2U1NjBiZWNjNzdhYWM2ZjY3ZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YjQzMTBmMmMzZmIyYTQ4ZGRmZmZlM2ZiZTI1MjMwNjJmNGJkY2Q1Nw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MzllODJkNDVmYzgyZTQzYzYzZjBhMWM4YmE2NmMzOWEwOGU0YmI2ZTdmMTEw
|
10
|
+
YzU2Y2E2MTg2ZGI2Njc3NTQ0N2I2YTU2YmFhZDc4NzdiZDk3ZTI5ZTFkN2Ix
|
11
|
+
ZGU5ZjJhMzc4NDkwM2U4NDljNmUyNmU5YjY3YzY2NzZjM2M2NDE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YTAwZjBlMzAwY2NmOTFlMmU1NGEwYzE4ODI3NWJmNjc0ZTIxNzNiMTAzMTNh
|
14
|
+
MTIxYzZiYTU4NzM2YzE5ZWZlNGFlMmIzNTIxOTYzN2U2NDNjMzIzNThmZDRm
|
15
|
+
N2NkZmJiZWIxMDQ5ZDdkMWEwNzI0ZThmYjg4OGFiMmM2Njg5YjI=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Dmitriy Nesteryuk
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,293 @@
|
|
1
|
+
# Whisperer
|
2
|
+
|
3
|
+
[](https://codeclimate.com/github/dnesteryuk/whisperer)
|
4
|
+
[](https://travis-ci.org/dnesteryuk/whisperer)
|
5
|
+
[](https://gemnasium.com/dnesteryuk/whisperer)
|
6
|
+
|
7
|
+
Do you hate fixtures? I do as well. The purpose of this library is to make your life easier when your application works with external API and you use VCR to stub that API.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
**Requirments**:
|
12
|
+
- Ruby 2.0.x or 2.1.x
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'whisperer'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install whisperer
|
25
|
+
|
26
|
+
To create default directories' structure and the config file with default options, you need to execute:
|
27
|
+
|
28
|
+
$ rake whisperer:install
|
29
|
+
|
30
|
+
It will create `cassette_builders` directory in your `spec` folder and `.whisperer.yml` file in your root directory of the project.
|
31
|
+
|
32
|
+
If you want to create only the config file, you need to execute:
|
33
|
+
|
34
|
+
$ rake whisperer:config:create
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
### Describing VCR cassettes
|
39
|
+
|
40
|
+
VCR cassettes are described in `cassette builders`. It is Ruby DSL which repeats structure of VCR cassette:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
Whisperer.define(:arya_stark) do
|
44
|
+
request do
|
45
|
+
uri 'http://example.com/users/1'
|
46
|
+
method :get
|
47
|
+
end
|
48
|
+
|
49
|
+
response do
|
50
|
+
status do
|
51
|
+
code 200
|
52
|
+
message 'OK'
|
53
|
+
end
|
54
|
+
|
55
|
+
headers do
|
56
|
+
content_type 'application/json;charset=utf-8'
|
57
|
+
end
|
58
|
+
|
59
|
+
body do
|
60
|
+
encoding 'UTF-8'
|
61
|
+
factory 'arya_stark', :json
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
recorded_at 'Mon, 13 Jan 2014 21:01:47 GMT'
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
But, it is Ruby, hence, we can benefit from that. Whisperer uses [FactoryGirl](/thoughtbot/factory_girl) to describe a response body. If you are not familar with FactoryGirl, please, make sure, you know how to use it bofore going on. There are a few ways how factories can be used.
|
70
|
+
|
71
|
+
You can use one single factory:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
body do
|
75
|
+
factory 'arya_stark' # we provide only name of the factory
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
`arya_stark` factory is taken to generate the response body:
|
80
|
+
|
81
|
+
```
|
82
|
+
string: '{"first_name":"Arya","last_name":"Stark","group":"member"}'
|
83
|
+
```
|
84
|
+
|
85
|
+
You can use multiple factories to generate collection for your response:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
body do
|
89
|
+
factories ['robb_stark', 'ned_stark'] # again we provide only names of factories
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
`robb_stark` and `ned_stark` are taken to generate the response body:
|
94
|
+
|
95
|
+
```
|
96
|
+
string: '[{"first_name":"Robb","last_name":"Stark","group":"member"},{"first_name":"Ned","last_name":"Stark","group":"member"}]'
|
97
|
+
```
|
98
|
+
|
99
|
+
You can pass factory objects instead of their names:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
body do
|
103
|
+
factories = (1..20).to_a.map do |i|
|
104
|
+
factories << FactoryGirl.build(
|
105
|
+
:article,
|
106
|
+
id: 'testid' + i,
|
107
|
+
title: 'test name' + i,
|
108
|
+
body: 'desc' + i
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
raw_data factories, :json_multiple
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
It is very useful, when you need generate dynamically instances of a factory.
|
117
|
+
|
118
|
+
#### Inheritance in cassette builders
|
119
|
+
|
120
|
+
If you need to generate almost the same VCR cassette, but with a bit differ data, you can do it via inheritance:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
Whisperer.define(:robb_stark, parent: :arya_stark) do
|
124
|
+
response do
|
125
|
+
body do
|
126
|
+
factory :robb_stark
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
132
|
+
In this case all data is taken from `aray_stark` cassette builder, only the response body is different.
|
133
|
+
|
134
|
+
You can redefine any option of VCR cassette:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
Whisperer.define(:robb_stark, parent: :arya_stark) do
|
138
|
+
request do
|
139
|
+
uri 'http://example.com/users/10'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
#### Request/Response Headers
|
145
|
+
|
146
|
+
While describing headers for a request or response you can use any kind of headers, they are dynamically created:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
headers do
|
150
|
+
content_length 100
|
151
|
+
content_type 'application/json'
|
152
|
+
x_requested_with 'XMLHttpRequest'
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
In a cassette it will look like:
|
157
|
+
|
158
|
+
```
|
159
|
+
Content-Length:
|
160
|
+
- '100'
|
161
|
+
Content-Type:
|
162
|
+
- application/json
|
163
|
+
X-Requested-With
|
164
|
+
- XMLHttpRequest
|
165
|
+
```
|
166
|
+
|
167
|
+
#### Placeholder for FactoryGirl
|
168
|
+
|
169
|
+
Since VCR is used to stub interractions with external services, there is a big chance that you don't have Ruby model to be used for defining factories. In most cases, you don't need them to generate VCR cassettes. Whisperer offers the placeholder class:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
FactoryGirl.define do
|
173
|
+
factory :arya_stark, class: Placeholder do
|
174
|
+
first_name 'Arya'
|
175
|
+
last_name 'Stark'
|
176
|
+
group 'member'
|
177
|
+
end
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
Placeholder is a simple class inheriting `OpenStruct` class:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
Placeholder = Class.new(OpenStruct)
|
185
|
+
```
|
186
|
+
|
187
|
+
It decouples factories from your application.
|
188
|
+
|
189
|
+
### Serializers for a response body
|
190
|
+
|
191
|
+
When an external API is subbed with VCR, API response has some format like Json, XML or any other formats. Whisperer supports possibility to convert factories into a format your external API uses. Such mechanism is provided by **serializers** which are used along with building a response body. Whisperer has only 2 serializers:
|
192
|
+
|
193
|
+
- json
|
194
|
+
- multiple json
|
195
|
+
|
196
|
+
`Json` serializer is used for serializing one single factory:
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
response do
|
200
|
+
body do
|
201
|
+
factory :robb_stark
|
202
|
+
serializer :json
|
203
|
+
end
|
204
|
+
end
|
205
|
+
```
|
206
|
+
|
207
|
+
The purpose of `json `serializer is to convert a given factory into Json format.
|
208
|
+
|
209
|
+
`Multiple Json` serializer is used for serializing a collection of factories:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
body do
|
213
|
+
factories ['robb_stark', 'ned_stark']
|
214
|
+
serializer :json_multiple
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
It is very similar to `Json` serializer, but in this case it goes through the array, builds factories, serializes a received array of objects.
|
219
|
+
|
220
|
+
If you need to define your own serializer, it is very easy to do. At first you need to define your own serializer class inhering `Whisperer::Serializes::Base` class:
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
class MySerializer < Whisperer::Serializers::Base
|
224
|
+
def serialize
|
225
|
+
do_something_with(@obj)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
*Note:* `@obj` is an `OpenStruct` instance in this example.
|
231
|
+
|
232
|
+
Then you need to register the new serializer:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
Whisperer.register_serializer(:my_serializer, Serializers::MySerializer)
|
236
|
+
```
|
237
|
+
|
238
|
+
Now, it can be used as any other serializer:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
response do
|
242
|
+
body do
|
243
|
+
factory :robb_stark
|
244
|
+
serializer :my_serializer
|
245
|
+
end
|
246
|
+
end
|
247
|
+
```
|
248
|
+
|
249
|
+
### Configuration
|
250
|
+
|
251
|
+
You can configure Whisperer through `.whisperer.yml` which should be created in a root directory of your project. It gives you following options:
|
252
|
+
|
253
|
+
- generate_to - the path to save generated cassettes
|
254
|
+
- builders_matcher - the pattern to find builders
|
255
|
+
- factories_matcher - the pattern to find factories
|
256
|
+
|
257
|
+
Example of such file:
|
258
|
+
|
259
|
+
```
|
260
|
+
generate_to: 'spec/cassettes/vcr_cassettes/'
|
261
|
+
builders_matcher: './spec/cassette_builders/**/*.rb'
|
262
|
+
factories_matcher: './spec/factories/*.rb'
|
263
|
+
```
|
264
|
+
|
265
|
+
### Generating cassettes
|
266
|
+
|
267
|
+
To generate cassettes based on cassette builders, you need to launch command:
|
268
|
+
|
269
|
+
$ rake whisperer:cassettes:generate_all
|
270
|
+
|
271
|
+
This command will generate new cassettes and re-generate all existing cassettes for VCR.
|
272
|
+
|
273
|
+
To generate only on particular cassette, you can use this command
|
274
|
+
|
275
|
+
$ rake whisperer:cassettes:generate[cassette_builder]
|
276
|
+
|
277
|
+
`cassette_builder` is a name of the cassette builder.
|
278
|
+
|
279
|
+
### Generating a sample for the cassette builder
|
280
|
+
|
281
|
+
Manual creation of cassette builders is painful. There is a command which can help you with that:
|
282
|
+
|
283
|
+
$ rake whisperer:cassettes:builders:sample
|
284
|
+
|
285
|
+
It creates a sample for you in the directory with cassette builders, you need to edit it only.
|
286
|
+
|
287
|
+
## Contributing
|
288
|
+
|
289
|
+
1. Fork it
|
290
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
291
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
292
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
293
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/TODO.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
## Release 0.0.1
|
2
|
+
|
3
|
+
1. Add info to doc:
|
4
|
+
- subpath for generating cassettes
|
5
|
+
- factories for requests
|
6
|
+
|
7
|
+
## Release 0.0.2
|
8
|
+
|
9
|
+
1. Think about the better way for inheriting serializes, now it looks like:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
class Whisperer::Serializers::Base
|
13
|
+
# ...
|
14
|
+
end
|
15
|
+
|
16
|
+
class Whisperer::Serializers::Json < Whisperer::Serializers::Base
|
17
|
+
# ...
|
18
|
+
end
|
19
|
+
|
20
|
+
class Whisperer::Serializers::JsonMultiple < Whisperer::Serializers::Json
|
21
|
+
# ...
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
If an user wants to inherit `Whisperer::Serializers::JsonMultiple` it will look even more crazy.
|
26
|
+
|
27
|
+
2. In most cases if we have a serializer for one single factory, we need a serializer for multiple factories. We need to write code which will create a multiple serializer automatically.
|
28
|
+
3. The Whisperer::Config.load method is too complex.
|
29
|
+
4. Create rake task for generating factories based on Vcr responses.
|
30
|
+
5. Try to find better way for defining dynamic attributes for headers, it doesn't work when you write:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
Whisperer::Record.new(
|
34
|
+
response: {
|
35
|
+
headers: {
|
36
|
+
content_length: 10
|
37
|
+
}
|
38
|
+
}
|
39
|
+
)
|
40
|
+
```
|
41
|
+
|
42
|
+
6. Refactore Whisperer::Record#merge_attrs! method, it should be moved to some another class
|
43
|
+
7. Refactore Whisperer.define method, it is another responsibility which should not leave in this module.
|
44
|
+
8. Think about the issue with touching Whisperer::cassette_records, it is not ok
|
45
|
+
9. `Whisperer::generate` and `Whisperer::generate_all` receive cassette records twice. Also, it is needless to check existence of a cassette record if it is passed from `generate_all` to `generate`.
|
46
|
+
10. Serializers must be stored similar to preprocessors (in the own module/class).
|
47
|
+
11. Check whether we can use a real model instead of OpenStruct while describing factories.
|
data/lib/whisperer.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'whisperer/version'
|
2
|
+
|
3
|
+
require 'virtus'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
require 'whisperer/config'
|
7
|
+
|
8
|
+
require 'whisperer/placeholder'
|
9
|
+
require 'whisperer/dsl'
|
10
|
+
require 'whisperer/helpers'
|
11
|
+
|
12
|
+
require 'whisperer/generator'
|
13
|
+
|
14
|
+
require 'whisperer/convertors/hash'
|
15
|
+
require 'whisperer/convertors/interaction'
|
16
|
+
|
17
|
+
require 'whisperer/serializers/json'
|
18
|
+
require 'whisperer/serializers/json_multiple'
|
19
|
+
|
20
|
+
require 'whisperer/preprocessors'
|
21
|
+
require 'whisperer/preprocessors/content_length'
|
22
|
+
require 'whisperer/preprocessors/response_body'
|
23
|
+
|
24
|
+
module Whisperer
|
25
|
+
@cassette_records = ThreadSafe::Hash.new
|
26
|
+
@serializers = ThreadSafe::Hash.new
|
27
|
+
|
28
|
+
class << self
|
29
|
+
attr_reader :cassette_records
|
30
|
+
attr_reader :serializers
|
31
|
+
|
32
|
+
def define(name, options = {}, &block)
|
33
|
+
dsl = Dsl.build
|
34
|
+
dsl.instance_eval &block
|
35
|
+
record = dsl.container
|
36
|
+
|
37
|
+
if options[:parent]
|
38
|
+
original_record = cassette_records[options[:parent]]
|
39
|
+
|
40
|
+
if original_record.nil?
|
41
|
+
raise ArgumentError.new("Parent record \"#{options[:parent]}\" is not declared.")
|
42
|
+
else
|
43
|
+
record.merge!(original_record)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
cassette_records[name.to_sym] = record
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns true if at least one factory is defined, otherwise returns false.
|
51
|
+
def defined_any?
|
52
|
+
cassette_records.size > 0
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate(name)
|
56
|
+
name = name.to_sym
|
57
|
+
|
58
|
+
unless cassette_records[name]
|
59
|
+
raise NocassetteRecordError.new("There is not cassette builder with \"#{name}\" name.")
|
60
|
+
end
|
61
|
+
|
62
|
+
container = cassette_records[name]
|
63
|
+
|
64
|
+
Generator.generate(container, name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def generate_all
|
68
|
+
if defined_any?
|
69
|
+
cassette_records.each do |name, container|
|
70
|
+
generate(name)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
raise NocassetteRecordError.new('cassette builders are not found.')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def serializer(name)
|
78
|
+
unless serializers[name]
|
79
|
+
raise ArgumentError.new("There is not serializer registered with \"#{name}\" name")
|
80
|
+
end
|
81
|
+
|
82
|
+
serializers[name]
|
83
|
+
end
|
84
|
+
|
85
|
+
def register_serializer(name, class_name)
|
86
|
+
serializers[name] = class_name
|
87
|
+
end
|
88
|
+
|
89
|
+
def register_preprocessor(name, class_name)
|
90
|
+
Preprocessors.register(name, class_name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class NocassetteRecordError < ArgumentError; end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
Whisperer.register_serializer(:json, Whisperer::Serializers::Json)
|
99
|
+
Whisperer.register_serializer(:json_multiple, Whisperer::Serializers::JsonMultiple)
|
100
|
+
|
101
|
+
Whisperer::register_preprocessor(:response_body, Whisperer::Preprocessors::ResponseBody)
|
102
|
+
Whisperer::register_preprocessor(:content_length, Whisperer::Preprocessors::ContentLength)
|