whisperer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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