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
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/users/2
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Content-Length:
|
16
|
+
- '14'
|
17
|
+
body:
|
18
|
+
encoding: UTF-8
|
19
|
+
string: '{"empty":true}'
|
20
|
+
http_version:
|
21
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
22
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/users/1
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Content-Length:
|
16
|
+
- '58'
|
17
|
+
Content-Type:
|
18
|
+
- application/json;charset=utf-8
|
19
|
+
body:
|
20
|
+
encoding: UTF-8
|
21
|
+
string: '{"first_name":"Arya","last_name":"Stark","group":"member"}'
|
22
|
+
http_version:
|
23
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
24
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/users/1
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Content-Length:
|
18
|
+
- '57'
|
19
|
+
Content-Type:
|
20
|
+
- application/json;charset=utf-8
|
21
|
+
X-Content-Type-Options:
|
22
|
+
- nosniff
|
23
|
+
body:
|
24
|
+
encoding: UTF-8
|
25
|
+
string: '{"first_name":"Robb","last_name":"Stark","group":"member"}'
|
26
|
+
http_version:
|
27
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
28
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/users/2
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Content-Length:
|
16
|
+
- '58'
|
17
|
+
body:
|
18
|
+
encoding: UTF-8
|
19
|
+
string: '{"first_name":"Robb","last_name":"Stark","group":"member"}'
|
20
|
+
http_version:
|
21
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
22
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/users/2
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Content-Length:
|
18
|
+
- 11
|
19
|
+
body:
|
20
|
+
encoding: UTF-8
|
21
|
+
string: Sansa Stark
|
22
|
+
http_version:
|
23
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
24
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/users
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Content-Length:
|
18
|
+
- '57'
|
19
|
+
Content-Type:
|
20
|
+
- application/json;charset=utf-8
|
21
|
+
X-Content-Type-Options:
|
22
|
+
- nosniff
|
23
|
+
body:
|
24
|
+
encoding: UTF-8
|
25
|
+
string: '[{"first_name":"Robb","last_name":"Stark","group":"member"},{"first_name":"Ned","last_name":"Stark","group":"member"}]'
|
26
|
+
http_version:
|
27
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
28
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://example.com/members
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- "*/*"
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Content-Length:
|
18
|
+
- '57'
|
19
|
+
Content-Type:
|
20
|
+
- application/json;charset=utf-8
|
21
|
+
X-Content-Type-Options:
|
22
|
+
- nosniff
|
23
|
+
body:
|
24
|
+
encoding: UTF-8
|
25
|
+
string: '[{"first_name":"Robb","last_name":"Stark","group":"member"},{"first_name":"Ned","last_name":"Stark","group":"member"}]'
|
26
|
+
http_version:
|
27
|
+
recorded_at: Mon, 13 Jan 2014 21:01:47 GMT
|
28
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_integration_helper'
|
2
|
+
|
3
|
+
describe 'Whisperer' do
|
4
|
+
after do
|
5
|
+
Dir["#{VCR.configuration.cassette_library_dir}/**/*.yml"].each do |file|
|
6
|
+
File.delete(file)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'when a simple factory is given' do
|
11
|
+
it 'generates a cassette' do
|
12
|
+
expect(cassette('robb_stark')).to eq(Whisperer.generate(:robb_stark))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when an array of factories is given' do
|
17
|
+
it 'generates a cassette' do
|
18
|
+
expect(cassette('starks')).to eq(Whisperer.generate(:starks))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when a cassette record inherits another cassette record' do
|
23
|
+
it 'generates a cassette with data from a parent cassette' do
|
24
|
+
expect(cassette('wolfs')).to eq(Whisperer.generate(:wolfs))
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'generates a cassette and uses the serializer defined in the parent builder' do
|
28
|
+
expect(cassette('sansa_stark')).to eq(Whisperer.generate(:sansa_stark))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when a cassette record is given without a defined content length for a response body' do
|
33
|
+
it 'generates a cassette with a content length which is calculated by size of a response body' do
|
34
|
+
expect(cassette('robb_stark_without_content_length')).to eq(
|
35
|
+
Whisperer.generate(:robb_stark_without_content_length)
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when a cassette record use a string to define a response body' do
|
41
|
+
it 'generates a cassette' do
|
42
|
+
expect(cassette('empty_robb_stark')).to eq(Whisperer.generate(:empty_robb_stark))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when a cassette record has a sub directory' do
|
47
|
+
it 'generates a cassette in a sub directory' do
|
48
|
+
expect(cassette('girls/arya_stark')).to eq(Whisperer.generate(:arya_stark))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
require 'rspec'
|
6
|
+
require 'factory_girl'
|
7
|
+
|
8
|
+
require 'whisperer'
|
9
|
+
|
10
|
+
require 'support/cassettes'
|
11
|
+
require 'support/custom_serializer'
|
12
|
+
|
13
|
+
Whisperer.register_serializer(:custom, CustomSerializer)
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.expect_with :rspec do |c|
|
17
|
+
c.syntax = :expect
|
18
|
+
end
|
19
|
+
|
20
|
+
config.include(Cassettes)
|
21
|
+
end
|
22
|
+
|
23
|
+
VCR.configure do |c|
|
24
|
+
c.cassette_library_dir = 'spec/generated_cassettes'
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Cassettes
|
2
|
+
# Returns content of a generated cassette
|
3
|
+
def cassette(cassette_name)
|
4
|
+
f = File.read('spec/cassettes/' << cassette_name << '.yml')
|
5
|
+
#, '"99*/*"'
|
6
|
+
if RUBY_VERSION =~ /2.0.\d+/
|
7
|
+
f.gsub(/("\*\/\*")/, '\'*/*\'')
|
8
|
+
elsif RUBY_VERSION =~ /2.1.0/
|
9
|
+
f.gsub(/string: '(.+)'/) do |found|
|
10
|
+
found.gsub('"', '\"').gsub('\'', '"')
|
11
|
+
end
|
12
|
+
else
|
13
|
+
f
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Whisperer::Config do
|
4
|
+
describe '.load' do
|
5
|
+
shared_examples 'initializes the config' do |parsed_yml|
|
6
|
+
it 'initializes the config object' do
|
7
|
+
expect(Whisperer::Config).to receive(:new).with(parsed_yml).and_return(config)
|
8
|
+
|
9
|
+
subject
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'VCR has a define path to cassettes' do
|
13
|
+
subject
|
14
|
+
|
15
|
+
expect(VCR.configuration.cassette_library_dir).to eq(dirname)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns the configuration object' do
|
19
|
+
res = subject
|
20
|
+
|
21
|
+
expect(res).to eq(config)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:dirname) { '/tmp' }
|
26
|
+
let(:config) { instance_double(Whisperer::Config, generate_to: dirname) }
|
27
|
+
|
28
|
+
subject { described_class }
|
29
|
+
|
30
|
+
before do
|
31
|
+
allow(Whisperer::Config).to receive(:new).and_return(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the configuration name is passed' do
|
35
|
+
context 'when the configuration file exists' do
|
36
|
+
subject { described_class.load('/tmp/whisperer.test') }
|
37
|
+
|
38
|
+
after do
|
39
|
+
File.delete('/tmp/whisperer.test')
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when it is not empty' do
|
43
|
+
before do
|
44
|
+
f = File.new('/tmp/whisperer.test', 'w')
|
45
|
+
f.write('test: 1')
|
46
|
+
f.close
|
47
|
+
end
|
48
|
+
|
49
|
+
it_behaves_like 'initializes the config', {"test" => 1}
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when it is empty' do
|
53
|
+
before do
|
54
|
+
File.new('/tmp/whisperer.test', 'w').close
|
55
|
+
end
|
56
|
+
|
57
|
+
it_behaves_like 'initializes the config', {}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when the configuration file does not exist' do
|
62
|
+
subject { described_class.load('/tmp/doesnotexist') }
|
63
|
+
|
64
|
+
it_behaves_like 'initializes the config', {}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when the configuration name is not passed' do
|
69
|
+
subject { described_class.load }
|
70
|
+
|
71
|
+
it_behaves_like 'initializes the config', {}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#to_yml' do
|
76
|
+
let(:options) {
|
77
|
+
{
|
78
|
+
generate_to: 'some dir',
|
79
|
+
builders_matcher: 'some builder matcher',
|
80
|
+
factories_matcher: 'some factories matcher'
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
subject { described_class.new(options) }
|
85
|
+
|
86
|
+
it 'returns yml record with the configuration options' do
|
87
|
+
expect(subject.to_yml).to eq(
|
88
|
+
"generate_to: '#{options[:generate_to]}'\n" <<
|
89
|
+
"builders_matcher: '#{options[:builders_matcher]}'\n" <<
|
90
|
+
"factories_matcher: '#{options[:factories_matcher]}'"
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|