whisperer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -13
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +2 -1
  4. data/README.md +80 -9
  5. data/TODO.md +30 -35
  6. data/lib/whisperer.rb +18 -48
  7. data/lib/whisperer/merger.rb +36 -0
  8. data/lib/whisperer/preprocessors/default_values.rb +22 -0
  9. data/lib/whisperer/preprocessors/response_body.rb +2 -2
  10. data/lib/whisperer/record.rb +2 -35
  11. data/lib/whisperer/record/body.rb +3 -3
  12. data/lib/whisperer/record/default_value.rb +13 -0
  13. data/lib/whisperer/record/headers.rb +6 -1
  14. data/lib/whisperer/record/request.rb +1 -1
  15. data/lib/whisperer/record/response.rb +1 -6
  16. data/lib/whisperer/record/response/status.rb +2 -2
  17. data/lib/whisperer/serializers.rb +21 -0
  18. data/lib/whisperer/serializers/json.rb +26 -1
  19. data/lib/whisperer/serializers/json_multiple.rb +1 -1
  20. data/lib/whisperer/storage.rb +41 -0
  21. data/lib/whisperer/tasks/whisperer.rake +3 -3
  22. data/lib/whisperer/version.rb +1 -1
  23. data/spec/cassettes/empty_robb_stark.yml +2 -2
  24. data/spec/cassettes/girls/arya_stark.yml +2 -2
  25. data/spec/cassettes/robb_stark.yml +2 -2
  26. data/spec/cassettes/robb_stark_without_content_length.yml +2 -2
  27. data/spec/cassettes/sansa_stark.yml +1 -1
  28. data/spec/cassettes/starks.yml +2 -2
  29. data/spec/cassettes/wolfs.yml +2 -2
  30. data/spec/unit/merger_spec.rb +98 -0
  31. data/spec/unit/preprocessors/content_length_spec.rb +9 -5
  32. data/spec/unit/preprocessors/default_values_spec.rb +26 -0
  33. data/spec/unit/preprocessors/response_body_spec.rb +4 -4
  34. data/spec/unit/record/headers_spec.rb +13 -1
  35. data/spec/unit/record_spec.rb +0 -73
  36. data/spec/unit/serializers/json_spec.rb +60 -12
  37. data/spec/unit/serializers_spec.rb +24 -0
  38. data/spec/unit/storage_spec.rb +82 -0
  39. data/spec/unit/whisperer_spec.rb +33 -103
  40. metadata +26 -12
@@ -6,15 +6,19 @@ describe Whisperer::Preprocessors::ContentLength do
6
6
 
7
7
  context 'when a content length for a response is defined' do
8
8
  let(:record) {
9
- r = Whisperer::Record.new
10
- r.response.headers.content_length = '10'
11
- r
9
+ Whisperer::Record.new(
10
+ response: {
11
+ headers: {
12
+ content_length: 10
13
+ }
14
+ }
15
+ )
12
16
  }
13
17
 
14
18
  it 'record has a unchanged content length' do
15
19
  subject.process
16
20
 
17
- expect(record.response.headers.content_length).to eq('10')
21
+ expect(record.response.headers.content_length).to eq(10)
18
22
  end
19
23
  end
20
24
 
@@ -32,7 +36,7 @@ describe Whisperer::Preprocessors::ContentLength do
32
36
  it 'measures size of body and writes it to the content length header of the response' do
33
37
  subject.process
34
38
 
35
- expect(record.response.headers.content_length).to eq('4')
39
+ expect(record.response.headers.content_length).to eq(4)
36
40
  end
37
41
  end
38
42
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Whisperer::Preprocessors::DefaultValues do
4
+ describe '#process' do
5
+ let(:record) {
6
+ r = Whisperer::Record.new
7
+ r.request.method = Whisperer::DefaultValue.new(:get)
8
+ r.response.status.code = Whisperer::DefaultValue.new(200)
9
+ r
10
+ }
11
+
12
+ subject { described_class.new(record) }
13
+
14
+ before do
15
+ subject.process
16
+ end
17
+
18
+ it 'has correct value for the request method' do
19
+ expect(record.request.method).to eq(:get)
20
+ end
21
+
22
+ it 'has correct value for the response status' do
23
+ expect(record.response.status.code).to eq(200)
24
+ end
25
+ end
26
+ end
@@ -8,7 +8,7 @@ describe Whisperer::Preprocessors::ResponseBody do
8
8
  let(:record) { Whisperer::Record.new }
9
9
 
10
10
  it 'does not serialize anything' do
11
- expect(Whisperer).to_not receive(:serializer)
11
+ expect(Whisperer::Serializers).to_not receive(:fetch)
12
12
 
13
13
  subject.process
14
14
  end
@@ -29,17 +29,17 @@ describe Whisperer::Preprocessors::ResponseBody do
29
29
  }
30
30
 
31
31
  before do
32
- allow(Whisperer).to receive(:serializer).and_return(serializer)
32
+ allow(Whisperer::Serializers).to receive(:fetch).and_return(serializer)
33
33
  allow(serializer).to receive(:serialize).and_return(serialized_data)
34
34
  end
35
35
 
36
36
  it 'gets the serializer' do
37
- expect(Whisperer).to receive(:serializer).with(:json)
37
+ expect(Whisperer::Serializers).to receive(:fetch).with(:json)
38
38
 
39
39
  subject.process
40
40
  end
41
41
 
42
- it 'serializes the respose body' do
42
+ it 'serializes the response body' do
43
43
  expect(serializer).to receive(:serialize).with(data_obj, {some: 'options'})
44
44
 
45
45
  subject.process
@@ -1,7 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Whisperer::Headers do
4
- describe '.to_hash' do
4
+ describe '.new' do
5
+ context 'when there is not such attribute' do
6
+ subject {
7
+ described_class.new(connection: 'keep-alive')
8
+ }
9
+
10
+ it 'adds them dynamically' do
11
+ expect(subject.connection).to eq('keep-alive')
12
+ end
13
+ end
14
+ end
15
+
16
+ describe '#to_hash' do
5
17
  subject {
6
18
  obj = described_class.new()
7
19
 
@@ -1,77 +1,4 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Whisperer::Record do
4
- describe '#merge!' do
5
- let(:record) {
6
- r = Whisperer::Record.new(
7
- request: {
8
- uri: 'http://google.com',
9
- },
10
- response: {
11
- body: {
12
- encoding: 'UTF-8',
13
- string: 'test'
14
- }
15
- },
16
- recorded_at: 'test data'
17
- )
18
-
19
- r.request.headers.attribute(:content_length, Integer)
20
- r.request.headers.attribute(:accept, String)
21
-
22
- r.request.headers.content_length = 100
23
- r.request.headers.accept = 'javascript'
24
- r
25
- }
26
-
27
- let(:another_record) {
28
- r = Whisperer::Record.new(
29
- request: {
30
- headers: {
31
- content_length: 50
32
- }
33
- },
34
- response: {
35
- body: {
36
- encoding: 'UTF-16'
37
- }
38
- }
39
- )
40
-
41
- r.request.headers.attribute(:content_length, Integer)
42
-
43
- r.request.headers.content_length = 50
44
- r
45
- }
46
-
47
- subject { another_record }
48
-
49
- before do
50
- subject.merge!(record)
51
- end
52
-
53
- it 'has a correct content length header for the request' do
54
- expect(subject.request.headers.content_length).to eq(50)
55
- end
56
-
57
- it 'has an accept header for the request' do
58
- expect(subject.request.headers.accept).to eq('javascript')
59
- end
60
-
61
- it 'has an url' do
62
- expect(subject.request.uri).to eq('http://google.com')
63
- end
64
-
65
- it 'has a correct encoding for the body of the response' do
66
- expect(subject.response.body.encoding).to eq('UTF-16')
67
- end
68
-
69
- it 'has a string for the body of the response' do
70
- expect(subject.response.body.string).to eq('test')
71
- end
72
-
73
- it 'has a correct recorded_at value' do
74
- expect(subject.recorded_at).to eq('test data')
75
- end
76
- end
77
4
  end
@@ -7,8 +7,48 @@ class TestChildJson < Whisperer::Serializers::Json
7
7
  end
8
8
  end
9
9
 
10
+ class TestObj
11
+ def initialize(attrs)
12
+ @first_name = attrs[:first_name]
13
+ @last_name = nil
14
+ end
15
+
16
+ # we need to make sure that our serializer uses accessors methods
17
+ # when it exists.
18
+ def last_name
19
+ 'Snow'
20
+ end
21
+ end
22
+
23
+ class TestObjWithAttrs
24
+ def attributes
25
+ {
26
+ first_name: 'John',
27
+ last_name: 'Snow'
28
+ }
29
+ end
30
+ end
31
+
10
32
  describe Whisperer::Serializers::Json do
11
33
  describe '#serialize' do
34
+ shared_examples 'serializing an object' do
35
+ it 'returns json string with serialized attributes' do
36
+ expect(subject.serialize).to eq('{"first_name":"John","last_name":"Snow"}')
37
+ end
38
+
39
+ context 'when the class is inherited' do
40
+ subject { TestChildJson.new(given_obj) }
41
+
42
+ context 'when the child class alters the data structure' do
43
+ it 'returns the altered structure' do
44
+ expect(subject.serialize).to eq(
45
+ '{"test":{"first_name":"John","last_name":"Snow"}}'
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+
12
52
  let(:attrs) {
13
53
  {
14
54
  first_name: 'John',
@@ -16,22 +56,30 @@ describe Whisperer::Serializers::Json do
16
56
  }
17
57
  }
18
58
 
19
- subject { described_class.new(OpenStruct.new(attrs)) }
59
+ subject { described_class.new(given_obj) }
60
+
61
+ context 'when an open struct object is given' do
62
+ let(:given_obj) {
63
+ OpenStruct.new(attrs)
64
+ }
65
+
66
+ it_behaves_like 'serializing an object'
67
+ end
68
+
69
+ context 'When a pure ruby object is given' do
70
+ let(:given_obj) {
71
+ TestObj.new(attrs)
72
+ }
20
73
 
21
- it 'returns json string with serialized attributes' do
22
- expect(subject.serialize).to eq('{"first_name":"John","last_name":"Snow"}')
74
+ it_behaves_like 'serializing an object'
23
75
  end
24
76
 
25
- context 'when the class is inherited' do
26
- subject { TestChildJson.new(OpenStruct.new(attrs)) }
77
+ context 'when an object has the attributes method' do
78
+ let(:given_obj) {
79
+ TestObjWithAttrs.new
80
+ }
27
81
 
28
- context 'when the child class alters the data structure' do
29
- it 'returns the altered structure' do
30
- expect(subject.serialize).to eq(
31
- '{"test":{"first_name":"John","last_name":"Snow"}}'
32
- )
33
- end
34
- end
82
+ it_behaves_like 'serializing an object'
35
83
  end
36
84
  end
37
85
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Whisperer::Serializers do
4
+ describe '.fetch' do
5
+ before do
6
+ described_class.register(:test_json, 'My test class')
7
+ end
8
+
9
+ context 'when there is not such serializer' do
10
+ it 'raises an error' do
11
+ expect { described_class.fetch(:mytest) }.to raise_error(
12
+ ArgumentError,
13
+ 'There is not serializer registered with "mytest" name'
14
+ )
15
+ end
16
+ end
17
+
18
+ context 'when there is such serializer' do
19
+ it 'returns the registered class' do
20
+ expect(described_class.fetch(:test_json)).to eq('My test class')
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Whisperer::Storage do
4
+ describe '.define' do
5
+ let(:cassette_record) { instance_double('Whisperer::Record') }
6
+ let(:dsl) { instance_double('Whisperer::Dsl', container: cassette_record) }
7
+
8
+ before do
9
+ allow(Whisperer::Dsl).to receive(:build).and_return(dsl)
10
+ end
11
+
12
+ after do
13
+ described_class.reset_storage
14
+ end
15
+
16
+ it 'builds the dsl object' do
17
+ expect(Whisperer::Dsl).to receive(:build)
18
+
19
+ described_class.define(:test) {}
20
+ end
21
+
22
+ it 'executes a given block over the dsl object' do
23
+ expect(dsl).to receive(:request)
24
+
25
+ described_class.define(:test) {
26
+ request
27
+ }
28
+ end
29
+
30
+ it 'stores the generated cassette record' do
31
+ described_class.define(:test) {}
32
+
33
+ expect(described_class.cassette_record(:test)).to eq(cassette_record)
34
+ expect(described_class.defined_any?).to be_truthy
35
+ end
36
+
37
+ context 'when a string as a name of the cassette record is given' do
38
+ it 'stores a cassette record with a symbol key' do
39
+ described_class.define('test') {}
40
+
41
+ expect(described_class.cassette_record(:test)).to eq(cassette_record)
42
+ end
43
+ end
44
+
45
+ context 'when a parent is defined for a cassette record' do
46
+ context 'when such parent exists' do
47
+ let(:orig_cassette_record) { double('original cassette record') }
48
+
49
+ before do
50
+ expect(described_class).to receive(:cassette_record).with(:some_parent).and_return(
51
+ orig_cassette_record
52
+ )
53
+ end
54
+
55
+ it 'merges the original record with the newly built' do
56
+ expect(Whisperer::Merger).to receive(:merge).with(
57
+ cassette_record,
58
+ orig_cassette_record
59
+ )
60
+
61
+ described_class.define('test', parent: :some_parent) {}
62
+ end
63
+ end
64
+
65
+ context 'when such parent does not exist' do
66
+ it 'raises an error' do
67
+ expect {
68
+ described_class.define('test', parent: :some_parent) {}
69
+ }.to raise_error(ArgumentError, 'Parent record "some_parent" is not declared.')
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '.defined_any?' do
76
+ context 'when there are not defined cassette_records' do
77
+ it 'returns false' do
78
+ expect(described_class.defined_any?).to be_falsey
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,94 +1,25 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Whisperer do
4
- after do
5
- described_class.cassette_records.clear
6
- end
7
-
8
4
  describe '.define' do
9
- let(:cassette_record) { instance_double('Whisperer::Record', merge!: true) }
10
- let(:dsl) { instance_double('Whisperer::Dsl', container: cassette_record) }
11
-
12
- before do
13
- allow(Whisperer::Dsl).to receive(:build).and_return(dsl)
14
- end
15
-
16
- it 'builds the dsl object' do
17
- expect(Whisperer::Dsl).to receive(:build)
18
-
19
- described_class.define(:test) {}
20
- end
21
-
22
- it 'executes a given block over the dsl object' do
23
- expect(dsl).to receive(:request)
24
-
25
- described_class.define(:test) {
26
- request
27
- }
28
- end
29
-
30
- it 'stores the generated cassette record' do
31
- described_class.define(:test) {}
5
+ it 'proxies to the storage class' do
6
+ expect(Whisperer::Storage).to receive(:define).with(
7
+ 'test arg'
8
+ )
32
9
 
33
- expect(Whisperer.cassette_records[:test]).to eq(cassette_record)
34
- end
35
-
36
- context 'when a string as a name of the cassette record is given' do
37
- it 'stores a cassette record with a symbol key' do
38
- described_class.define('test') {}
39
-
40
- expect(Whisperer.cassette_records[:test]).to eq(cassette_record)
41
- end
42
- end
43
-
44
- context 'when a parent is defined for a cassette record' do
45
- context 'when such parent exists' do
46
- let(:orig_cassette_record) { double('original cassette record') }
47
-
48
- before do
49
- Whisperer.cassette_records[:some_parent] = orig_cassette_record
50
- end
51
-
52
- it 'merges the original record with the newly built' do
53
- expect(cassette_record).to receive(:merge!).with(orig_cassette_record)
54
-
55
- described_class.define('test', parent: :some_parent) {}
56
- end
57
- end
58
-
59
- context 'when such parent does not exist' do
60
- it 'raises an error' do
61
- expect {
62
- described_class.define('test', parent: :some_parent) {}
63
- }.to raise_error(ArgumentError, 'Parent record "some_parent" is not declared.')
64
- end
65
- end
10
+ described_class.define('test arg')
66
11
  end
67
12
  end
68
13
 
69
- describe '.defined_any?' do
70
- context 'when there are defined cassette records' do
14
+ describe '.generate' do
15
+ context 'when the cassette record with the given name does not exist' do
71
16
  before do
72
- described_class.cassette_records[:test] = true
17
+ expect(Whisperer::Storage).to receive(:cassette_record).and_return(nil)
73
18
  end
74
19
 
75
- it 'returns true' do
76
- expect(Whisperer.defined_any?).to be_truthy
77
- end
78
- end
79
-
80
- context 'when there are not defined cassette_records' do
81
- it 'returns false' do
82
- expect(Whisperer.defined_any?).to be_falsey
83
- end
84
- end
85
- end
86
-
87
- describe '.generate' do
88
- context 'when the cassette record with the given name does not exist' do
89
20
  it 'raises an error' do
90
21
  expect { described_class.generate(:mytest) }.to raise_error(
91
- Whisperer::NocassetteRecordError,
22
+ Whisperer::NoCassetteRecordError,
92
23
  'There is not cassette builder with "mytest" name.'
93
24
  )
94
25
  end
@@ -109,7 +40,7 @@ describe Whisperer do
109
40
  let(:cassette_record) { double }
110
41
 
111
42
  before do
112
- described_class.cassette_records[:test] = cassette_record
43
+ expect(Whisperer::Storage).to receive(:cassette_record).with(:test).and_return(cassette_record)
113
44
  end
114
45
 
115
46
  context 'when the given name is a symbol' do
@@ -124,25 +55,33 @@ describe Whisperer do
124
55
 
125
56
  describe '.generate_all' do
126
57
  context 'when there are defined cassettes' do
127
- let(:record1) { double('cassette record 1') }
128
- let(:record2) { double('cassette record 2') }
58
+ let(:record1) { double('Cassette record 1') }
59
+ let(:record2) { double('Cassette record 2') }
129
60
 
130
61
  before do
131
- Whisperer::cassette_records[:record1] = record1
132
- Whisperer::cassette_records[:record2] = record2
62
+ expect(Whisperer::Storage).to receive(:cassette_records).and_return(
63
+ record1: record1,
64
+ record2: record2
65
+ )
133
66
 
134
- allow(Whisperer).to receive(:defined_any?).and_return(true)
135
- allow(Whisperer).to receive(:generate)
67
+ allow(Whisperer::Storage).to receive(:defined_any?).and_return(true)
68
+ allow(Whisperer::Generator).to receive(:generate)
136
69
  end
137
70
 
138
71
  it 'generates the VCR cassette based on record1' do
139
- expect(Whisperer).to receive(:generate).with(:record1)
72
+ expect(Whisperer::Generator).to receive(:generate).with(
73
+ record1,
74
+ :record1
75
+ )
140
76
 
141
77
  described_class.generate_all
142
78
  end
143
79
 
144
80
  it 'generates the VCR cassette based on record2' do
145
- expect(Whisperer).to receive(:generate).with(:record2)
81
+ expect(Whisperer::Generator).to receive(:generate).with(
82
+ record2,
83
+ :record2
84
+ )
146
85
 
147
86
  described_class.generate_all
148
87
  end
@@ -155,32 +94,23 @@ describe Whisperer do
155
94
 
156
95
  it 'raises and error' do
157
96
  expect { described_class.generate_all }.to raise_error(
158
- Whisperer::NocassetteRecordError,
159
- 'cassette builders are not found.'
97
+ Whisperer::NoCassetteRecordError,
98
+ 'Cassette builders are not found.'
160
99
  )
161
100
  end
162
101
  end
163
102
  end
164
103
 
165
- describe '.serializer' do
166
- context 'when there is not such serializer' do
167
- it 'raises an error' do
168
- expect { described_class.serializer(:mytest) }.to raise_error(
169
- ArgumentError,
170
- 'There is not serializer registered with "mytest" name'
171
- )
172
- end
173
- end
104
+ describe '.register_serializer' do
105
+ it 'registers a serializer' do
106
+ expect(Whisperer::Serializers).to receive(:register).with('some name', 'some class')
174
107
 
175
- context 'when there is such serializer' do
176
- it 'returns the registered class' do
177
- expect(described_class.serializer(:json)).to eq(Whisperer::Serializers::Json)
178
- end
108
+ Whisperer.register_serializer('some name', 'some class')
179
109
  end
180
110
  end
181
111
 
182
112
  describe '.register_preprocessor' do
183
- it 'registers preprocessor' do
113
+ it 'registers a preprocessor' do
184
114
  expect(Whisperer::Preprocessors).to receive(:register).with('some name', 'some class')
185
115
 
186
116
  Whisperer.register_preprocessor('some name', 'some class')