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.
Files changed (88) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +293 -0
  8. data/Rakefile +1 -0
  9. data/TODO.md +47 -0
  10. data/lib/whisperer.rb +102 -0
  11. data/lib/whisperer/config.rb +40 -0
  12. data/lib/whisperer/convertors/hash.rb +39 -0
  13. data/lib/whisperer/convertors/interaction.rb +21 -0
  14. data/lib/whisperer/dsl.rb +19 -0
  15. data/lib/whisperer/dsl/base.rb +47 -0
  16. data/lib/whisperer/dsl/body.rb +33 -0
  17. data/lib/whisperer/dsl/headers.rb +20 -0
  18. data/lib/whisperer/dsl/request.rb +15 -0
  19. data/lib/whisperer/dsl/response.rb +15 -0
  20. data/lib/whisperer/dsl/response/status.rb +10 -0
  21. data/lib/whisperer/generator.rb +43 -0
  22. data/lib/whisperer/helpers.rb +16 -0
  23. data/lib/whisperer/placeholder.rb +14 -0
  24. data/lib/whisperer/preprocessors.rb +19 -0
  25. data/lib/whisperer/preprocessors/base.rb +13 -0
  26. data/lib/whisperer/preprocessors/content_length.rb +17 -0
  27. data/lib/whisperer/preprocessors/response_body.rb +23 -0
  28. data/lib/whisperer/record.rb +48 -0
  29. data/lib/whisperer/record/body.rb +15 -0
  30. data/lib/whisperer/record/headers.rb +22 -0
  31. data/lib/whisperer/record/request.rb +16 -0
  32. data/lib/whisperer/record/response.rb +18 -0
  33. data/lib/whisperer/record/response/status.rb +10 -0
  34. data/lib/whisperer/samples/cassette_builder.rb +24 -0
  35. data/lib/whisperer/serializers/base.rb +24 -0
  36. data/lib/whisperer/serializers/json.rb +33 -0
  37. data/lib/whisperer/serializers/json_multiple.rb +14 -0
  38. data/lib/whisperer/tasks/whisperer.rake +88 -0
  39. data/lib/whisperer/version.rb +3 -0
  40. data/spec/cassette_builders/arya_stark.rb +26 -0
  41. data/spec/cassette_builders/bran_stark.rb +19 -0
  42. data/spec/cassette_builders/empty_robb_stark.rb +20 -0
  43. data/spec/cassette_builders/robb_stark.rb +30 -0
  44. data/spec/cassette_builders/robb_stark_without_content_length.rb +20 -0
  45. data/spec/cassette_builders/sansa_stark.rb +9 -0
  46. data/spec/cassette_builders/starks.rb +31 -0
  47. data/spec/cassette_builders/wolfs.rb +7 -0
  48. data/spec/cassettes/empty_robb_stark.yml +22 -0
  49. data/spec/cassettes/girls/arya_stark.yml +24 -0
  50. data/spec/cassettes/robb_stark.yml +28 -0
  51. data/spec/cassettes/robb_stark_without_content_length.yml +22 -0
  52. data/spec/cassettes/sansa_stark.yml +24 -0
  53. data/spec/cassettes/starks.yml +28 -0
  54. data/spec/cassettes/wolfs.yml +28 -0
  55. data/spec/factories/arya_stark.rb +7 -0
  56. data/spec/factories/bran_stark.rb +7 -0
  57. data/spec/factories/ned_stark.rb +7 -0
  58. data/spec/factories/robb_stark.rb +7 -0
  59. data/spec/factories/sansa_stark.rb +7 -0
  60. data/spec/integration/whisperer_spec.rb +51 -0
  61. data/spec/spec_helper.rb +25 -0
  62. data/spec/spec_integration_helper.rb +6 -0
  63. data/spec/support/cassettes.rb +16 -0
  64. data/spec/support/custom_serializer.rb +5 -0
  65. data/spec/unit/config_spec.rb +94 -0
  66. data/spec/unit/convertors/hash_spec.rb +59 -0
  67. data/spec/unit/convertors/interaction_spec.rb +46 -0
  68. data/spec/unit/dsl/base_spec.rb +99 -0
  69. data/spec/unit/dsl/body_spec.rb +73 -0
  70. data/spec/unit/dsl/headers_spec.rb +31 -0
  71. data/spec/unit/dsl/request_spec.rb +4 -0
  72. data/spec/unit/dsl/response_spec.rb +4 -0
  73. data/spec/unit/dsl/status_spec.rb +4 -0
  74. data/spec/unit/dsl_spec.rb +4 -0
  75. data/spec/unit/generator_spec.rb +77 -0
  76. data/spec/unit/helpers_spec.rb +38 -0
  77. data/spec/unit/preprocessors/content_length_spec.rb +39 -0
  78. data/spec/unit/preprocessors/response_body_spec.rb +55 -0
  79. data/spec/unit/preprocessors_spec.rb +8 -0
  80. data/spec/unit/record/headers_spec.rb +21 -0
  81. data/spec/unit/record/response_spec.rb +11 -0
  82. data/spec/unit/record_spec.rb +77 -0
  83. data/spec/unit/serializers/base_spec.rb +19 -0
  84. data/spec/unit/serializers/json_multiple_spec.rb +24 -0
  85. data/spec/unit/serializers/json_spec.rb +37 -0
  86. data/spec/unit/whisperer_spec.rb +189 -0
  87. data/whisperer.gemspec +28 -0
  88. metadata +277 -0
@@ -0,0 +1,7 @@
1
+ require_relative 'starks'
2
+
3
+ Whisperer.define(:wolfs, parent: :starks) do
4
+ request do
5
+ uri 'http://example.com/members'
6
+ end
7
+ end
@@ -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,7 @@
1
+ FactoryGirl.define do
2
+ factory :arya_stark, class: Placeholder do
3
+ first_name 'Arya'
4
+ last_name 'Stark'
5
+ group 'member'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :bran_stark, class: Placeholder do
3
+ first_name 'Bran'
4
+ last_name 'Stark'
5
+ group 'member'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :ned_stark, class: Placeholder do
3
+ first_name 'Ned'
4
+ last_name 'Stark'
5
+ group 'member'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :robb_stark, class: Placeholder do
3
+ first_name 'Robb'
4
+ last_name 'Stark'
5
+ group 'member'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :sansa_stark, class: Placeholder do
3
+ first_name 'Sansa'
4
+ last_name 'Stark'
5
+ group 'member'
6
+ end
7
+ end
@@ -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
@@ -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,6 @@
1
+ require 'spec_helper'
2
+
3
+ Dir[
4
+ './spec/factories/**/*.rb',
5
+ './spec/cassette_builders/**/*.rb'
6
+ ].each {|f| require f }
@@ -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,5 @@
1
+ class CustomSerializer
2
+ def self.serialize(record, options = {})
3
+ "#{record.first_name} #{record.last_name}"
4
+ end
5
+ 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