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,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Test
|
4
|
+
class Status
|
5
|
+
include Virtus.model
|
6
|
+
|
7
|
+
attribute :code, Integer
|
8
|
+
end
|
9
|
+
|
10
|
+
class Position
|
11
|
+
include Virtus.model
|
12
|
+
|
13
|
+
attribute :name
|
14
|
+
attribute :status, Status
|
15
|
+
end
|
16
|
+
|
17
|
+
class User
|
18
|
+
include Virtus.model
|
19
|
+
|
20
|
+
attribute :name, String
|
21
|
+
attribute :position, Test::Position
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Whisperer::Convertors::Hash do
|
26
|
+
describe '#convert' do
|
27
|
+
let(:attrs) {
|
28
|
+
{
|
29
|
+
name: 'Tester',
|
30
|
+
position: {
|
31
|
+
name: 'developer',
|
32
|
+
status: {
|
33
|
+
code: 1
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
let(:expected_attrs) {
|
40
|
+
{
|
41
|
+
'name' => 'Tester',
|
42
|
+
'position' => {
|
43
|
+
'name' => 'developer',
|
44
|
+
'status' => {
|
45
|
+
'code' => 1
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
subject { described_class.new(Test::User.new(attrs)) }
|
52
|
+
|
53
|
+
it 'returns a hash with all related objects' do
|
54
|
+
expect(subject.convert).to eq(
|
55
|
+
expected_attrs
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Whisperer::Convertors::Interaction do
|
4
|
+
describe '#convert' do
|
5
|
+
let(:obj) { double }
|
6
|
+
|
7
|
+
let(:hash) {
|
8
|
+
{
|
9
|
+
'request' => {
|
10
|
+
'uri' => 'http://google.com',
|
11
|
+
'method' => :get
|
12
|
+
},
|
13
|
+
'response' => {
|
14
|
+
'body' => 'test body'
|
15
|
+
},
|
16
|
+
'recorded_at' => Time.now.httpdate
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
subject { described_class.new(obj).convert }
|
21
|
+
|
22
|
+
before do
|
23
|
+
allow(Whisperer::Convertors::Hash).to receive(:convert).and_return(hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'converts the given record to hash' do
|
27
|
+
expect(Whisperer::Convertors::Hash).to receive(:convert).with(obj).and_return(hash)
|
28
|
+
|
29
|
+
subject
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'returns the VCR interraction object' do
|
33
|
+
it 'has a proper url' do
|
34
|
+
expect(subject.request.uri).to eq(hash['request']['uri'])
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'has a proper HTTP method' do
|
38
|
+
expect(subject.request.method).to eq(hash['request']['method'])
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'has a proper response body' do
|
42
|
+
expect(subject.response.body).to eq(hash['response']['body'])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Whisperer::BaseDsl do
|
4
|
+
context 'class method' do
|
5
|
+
describe '.link_dsl' do
|
6
|
+
before :all do
|
7
|
+
described_class.link_dsl('headers')
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'using of the generated method for accessing sub DSL' do
|
11
|
+
let(:headers_container) { double('headers container') }
|
12
|
+
|
13
|
+
let(:container) do
|
14
|
+
double(
|
15
|
+
'container',
|
16
|
+
headers: headers_container
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:headers) { double('Whisperer::Dsl::Headers') }
|
21
|
+
|
22
|
+
subject { described_class.new(container) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
allow(Whisperer::Dsl::Headers).to receive(:new).and_return(headers)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'initializes the header dsl object' do
|
29
|
+
expect(Whisperer::Dsl::Headers).to receive(:new).with(headers_container)
|
30
|
+
|
31
|
+
subject.headers {}
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'executes a given block over the header dsl object' do
|
35
|
+
expect(headers).to receive(:accept).with('test')
|
36
|
+
|
37
|
+
subject.headers {
|
38
|
+
accept 'test'
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.build' do
|
45
|
+
context 'when there is a linked container class' do
|
46
|
+
let(:request) { instance_double('Whisperer::Request') }
|
47
|
+
|
48
|
+
before do
|
49
|
+
described_class.link_container_class(Whisperer::Request)
|
50
|
+
|
51
|
+
allow(Whisperer::Request).to receive(:new).and_return(request)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'initializes a new instance of an object for keeping data' do
|
55
|
+
expect(Whisperer::Request).to receive(:new)
|
56
|
+
|
57
|
+
described_class.build
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'initializes a new instance of the dsl' do
|
61
|
+
expect(described_class).to receive(:new).with(request)
|
62
|
+
|
63
|
+
described_class.build
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when there is not a linked container class' do
|
68
|
+
before do
|
69
|
+
described_class.instance_variable_set(:@container_class, nil)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'raises an error' do
|
73
|
+
expect { described_class.build }.to raise_error(
|
74
|
+
ArgumentError,
|
75
|
+
'You should associate a container (model) with this dsl class, before building it'
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '.add_writer' do
|
82
|
+
context 'using of the generated method for writing data to the container' do
|
83
|
+
let(:container) { double }
|
84
|
+
|
85
|
+
before :all do
|
86
|
+
described_class.add_writer('some_attr')
|
87
|
+
end
|
88
|
+
|
89
|
+
subject { described_class.new(container) }
|
90
|
+
|
91
|
+
it 'writes a given value to the container' do
|
92
|
+
expect(container).to receive("some_attr=").with('my value')
|
93
|
+
|
94
|
+
subject.some_attr('my value')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
TestUser = Class.new(OpenStruct)
|
4
|
+
|
5
|
+
FactoryGirl.define do
|
6
|
+
factory :john_snow, class: TestUser do
|
7
|
+
name 'John Snow'
|
8
|
+
end
|
9
|
+
|
10
|
+
factory :eddard_stark, class: TestUser do
|
11
|
+
name 'Eddard Stark'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Whisperer::Dsl::Body do
|
16
|
+
let(:serialized_data) { 'serialized data' }
|
17
|
+
let(:container) { instance_double('Whisperer::Body', :string= => true) }
|
18
|
+
let(:serializer) { double('Serialize', serialize: true) }
|
19
|
+
|
20
|
+
subject { described_class.new(container) }
|
21
|
+
|
22
|
+
before do
|
23
|
+
allow(Whisperer).to receive(:serializer).and_return(serializer)
|
24
|
+
allow(serializer).to receive(:serialize).and_return(serialized_data)
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#factory' do
|
28
|
+
it 'writes a factory' do
|
29
|
+
expect(subject).to receive(:raw_data) do |model|
|
30
|
+
expect(model.name).to eq('John Snow')
|
31
|
+
end
|
32
|
+
|
33
|
+
subject.factory(:john_snow)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#factories' do
|
38
|
+
it 'writes factories' do
|
39
|
+
expect(subject).to receive(:raw_data) do |model|
|
40
|
+
expect(model.first.name).to eq('John Snow')
|
41
|
+
expect(model.last.name).to eq('Eddard Stark')
|
42
|
+
end
|
43
|
+
|
44
|
+
subject.factories([:john_snow, :eddard_stark])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#raw_data' do
|
49
|
+
let(:container) { instance_double('Whisperer::Body', :data_obj= => true, :serializer_opts= => true) }
|
50
|
+
|
51
|
+
it 'assigns the data object to the container' do
|
52
|
+
expect(container).to receive(:data_obj=).with('test obj')
|
53
|
+
|
54
|
+
subject.raw_data('test obj')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'assigns the serializer options to the container' do
|
58
|
+
expect(container).to receive(:serializer_opts=).with('test options')
|
59
|
+
|
60
|
+
subject.raw_data(nil, 'test options')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#serializer' do
|
65
|
+
let(:container) { instance_double('Whisperer::Body', :serializer= => true) }
|
66
|
+
|
67
|
+
it 'converts the name to the symbol and assigns to the container' do
|
68
|
+
expect(container).to receive(:serializer=).with(:test_name)
|
69
|
+
|
70
|
+
subject.serializer 'test_name'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Whisperer::Dsl::Headers do
|
4
|
+
let(:container) { Whisperer::Headers.new }
|
5
|
+
|
6
|
+
subject { described_class.new(container) }
|
7
|
+
|
8
|
+
describe '#method_missing' do
|
9
|
+
it 'defines the accept attribute' do
|
10
|
+
subject.accept('text/plain')
|
11
|
+
|
12
|
+
expect(
|
13
|
+
container.respond_to?(:accept)
|
14
|
+
).to be_truthy
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'assigns the value to the newly defined accept method' do
|
18
|
+
subject.accept('text/plain')
|
19
|
+
|
20
|
+
expect(container.accept).to eq('text/plain')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#respond_to?' do
|
25
|
+
it 'responds to the accept method' do
|
26
|
+
subject.accept('text/plain')
|
27
|
+
|
28
|
+
expect(subject.respond_to?(:accept)).to be_truthy
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Whisperer::Generator do
|
4
|
+
let(:record) { double(sub_path: 'test') }
|
5
|
+
|
6
|
+
let(:hash) {
|
7
|
+
{
|
8
|
+
'request' => {
|
9
|
+
'uri' => 'http://google.com',
|
10
|
+
'method' => :get
|
11
|
+
},
|
12
|
+
'response' => {
|
13
|
+
'body' => 'test body'
|
14
|
+
},
|
15
|
+
'recorded_at' => Time.now.httpdate
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:interraction) do
|
20
|
+
VCR::HTTPInteraction.from_hash(hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#generate' do
|
24
|
+
let(:path_to_cassette_dir) { VCR.configuration.cassette_library_dir + '/test/' }
|
25
|
+
let(:path_to_cassette) { path_to_cassette_dir + 'testcassette.yml' }
|
26
|
+
|
27
|
+
subject { described_class.new(record, 'testcassette') }
|
28
|
+
|
29
|
+
before do
|
30
|
+
allow(Whisperer::Preprocessors).to receive(:process!).and_return(record)
|
31
|
+
allow(Whisperer::Convertors::Interaction).to receive(:convert).and_return(interraction)
|
32
|
+
end
|
33
|
+
|
34
|
+
after do
|
35
|
+
File.delete(path_to_cassette)
|
36
|
+
Dir.delete(path_to_cassette_dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'processes preprocessors' do
|
40
|
+
expect(Whisperer::Preprocessors).to receive(:process!).with(record)
|
41
|
+
|
42
|
+
subject.generate
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'converts the record into VCR http interraction object' do
|
46
|
+
expect(Whisperer::Convertors::Interaction).to receive(:convert).with(record).and_return(interraction)
|
47
|
+
|
48
|
+
subject.generate
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'generates a VCR cassette' do
|
52
|
+
subject.generate
|
53
|
+
|
54
|
+
expect(
|
55
|
+
File.exists?(path_to_cassette)
|
56
|
+
).to be_truthy
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns a generated cassette' do
|
60
|
+
subject.generate
|
61
|
+
|
62
|
+
expect(subject.generate).to match(/http_interactions:/)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'removes the duplication' do
|
66
|
+
Dir.mkdir(path_to_cassette_dir)
|
67
|
+
|
68
|
+
f = File.open(path_to_cassette, 'w')
|
69
|
+
f.write('mytest')
|
70
|
+
f.close
|
71
|
+
|
72
|
+
subject.generate
|
73
|
+
|
74
|
+
expect(subject.generate).to_not match(/mytest/)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
FakeClass = Class.new do
|
4
|
+
def process; end
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Whisperer::Helpers do
|
8
|
+
describe '.add_builder' do
|
9
|
+
let(:obj) { 'some simple object' }
|
10
|
+
|
11
|
+
let(:faker) {
|
12
|
+
instance_double('FakeClass', process: true)
|
13
|
+
}
|
14
|
+
|
15
|
+
before(:all) do
|
16
|
+
FakeClass.extend(Whisperer::Helpers)
|
17
|
+
FakeClass.add_builder(:process)
|
18
|
+
end
|
19
|
+
|
20
|
+
before do
|
21
|
+
allow(FakeClass).to receive(:new).and_return(faker)
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { FakeClass.process(obj) }
|
25
|
+
|
26
|
+
it 'initializes the fake object' do
|
27
|
+
expect(FakeClass).to receive(:new).with(obj)
|
28
|
+
|
29
|
+
subject
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'serializes an object' do
|
33
|
+
expect(faker).to receive(:process)
|
34
|
+
|
35
|
+
subject
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|