evil-client 0.3.3 → 1.0.0

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 (180) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +0 -11
  3. data/.gitignore +1 -0
  4. data/.rspec +0 -1
  5. data/.rubocop.yml +22 -19
  6. data/.travis.yml +1 -0
  7. data/CHANGELOG.md +251 -6
  8. data/LICENSE.txt +3 -1
  9. data/README.md +47 -81
  10. data/docs/helpers/body.md +93 -0
  11. data/docs/helpers/connection.md +19 -0
  12. data/docs/helpers/headers.md +72 -0
  13. data/docs/helpers/http_method.md +39 -0
  14. data/docs/helpers/let.md +14 -0
  15. data/docs/helpers/logger.md +24 -0
  16. data/docs/helpers/middleware.md +56 -0
  17. data/docs/helpers/operation.md +103 -0
  18. data/docs/helpers/option.md +50 -0
  19. data/docs/helpers/path.md +37 -0
  20. data/docs/helpers/query.md +59 -0
  21. data/docs/helpers/response.md +40 -0
  22. data/docs/helpers/scope.md +121 -0
  23. data/docs/helpers/security.md +102 -0
  24. data/docs/helpers/validate.md +68 -0
  25. data/docs/index.md +70 -78
  26. data/docs/license.md +5 -1
  27. data/docs/rspec.md +96 -0
  28. data/evil-client.gemspec +10 -8
  29. data/lib/evil/client.rb +126 -72
  30. data/lib/evil/client/builder.rb +47 -0
  31. data/lib/evil/client/builder/operation.rb +40 -0
  32. data/lib/evil/client/builder/scope.rb +31 -0
  33. data/lib/evil/client/chaining.rb +17 -0
  34. data/lib/evil/client/connection.rb +60 -20
  35. data/lib/evil/client/container.rb +66 -0
  36. data/lib/evil/client/container/operation.rb +23 -0
  37. data/lib/evil/client/container/scope.rb +28 -0
  38. data/lib/evil/client/exceptions/definition_error.rb +15 -0
  39. data/lib/evil/client/exceptions/name_error.rb +32 -0
  40. data/lib/evil/client/exceptions/response_error.rb +42 -0
  41. data/lib/evil/client/exceptions/type_error.rb +29 -0
  42. data/lib/evil/client/exceptions/validation_error.rb +27 -0
  43. data/lib/evil/client/formatter.rb +49 -0
  44. data/lib/evil/client/formatter/form.rb +45 -0
  45. data/lib/evil/client/formatter/multipart.rb +33 -0
  46. data/lib/evil/client/formatter/part.rb +66 -0
  47. data/lib/evil/client/formatter/text.rb +21 -0
  48. data/lib/evil/client/resolver.rb +84 -0
  49. data/lib/evil/client/resolver/body.rb +22 -0
  50. data/lib/evil/client/resolver/format.rb +30 -0
  51. data/lib/evil/client/resolver/headers.rb +46 -0
  52. data/lib/evil/client/resolver/http_method.rb +34 -0
  53. data/lib/evil/client/resolver/middleware.rb +36 -0
  54. data/lib/evil/client/resolver/query.rb +39 -0
  55. data/lib/evil/client/resolver/request.rb +96 -0
  56. data/lib/evil/client/resolver/response.rb +26 -0
  57. data/lib/evil/client/resolver/security.rb +113 -0
  58. data/lib/evil/client/resolver/uri.rb +35 -0
  59. data/lib/evil/client/rspec.rb +127 -0
  60. data/lib/evil/client/schema.rb +105 -0
  61. data/lib/evil/client/schema/operation.rb +177 -0
  62. data/lib/evil/client/schema/scope.rb +73 -0
  63. data/lib/evil/client/settings.rb +172 -0
  64. data/lib/evil/client/settings/validator.rb +64 -0
  65. data/mkdocs.yml +21 -15
  66. data/spec/features/custom_connection_spec.rb +17 -0
  67. data/spec/features/operation/middleware_spec.rb +50 -0
  68. data/spec/features/operation/options_spec.rb +71 -0
  69. data/spec/features/operation/request_spec.rb +94 -0
  70. data/spec/features/operation/response_spec.rb +48 -0
  71. data/spec/features/scope/options_spec.rb +52 -0
  72. data/spec/fixtures/locales/en.yml +16 -0
  73. data/spec/fixtures/test_client.rb +76 -0
  74. data/spec/spec_helper.rb +18 -6
  75. data/spec/support/fixtures_helper.rb +7 -0
  76. data/spec/unit/builder/operation_spec.rb +90 -0
  77. data/spec/unit/builder/scope_spec.rb +84 -0
  78. data/spec/unit/client_spec.rb +137 -0
  79. data/spec/unit/connection_spec.rb +78 -0
  80. data/spec/unit/container/operation_spec.rb +81 -0
  81. data/spec/unit/container/scope_spec.rb +61 -0
  82. data/spec/unit/container_spec.rb +107 -0
  83. data/spec/unit/exceptions/definition_error_spec.rb +15 -0
  84. data/spec/unit/exceptions/name_error_spec.rb +77 -0
  85. data/spec/unit/exceptions/response_error_spec.rb +22 -0
  86. data/spec/unit/exceptions/type_error_spec.rb +71 -0
  87. data/spec/unit/exceptions/validation_error_spec.rb +13 -0
  88. data/spec/unit/formatter/form_spec.rb +27 -0
  89. data/spec/unit/formatter/multipart_spec.rb +23 -0
  90. data/spec/unit/formatter/part_spec.rb +49 -0
  91. data/spec/unit/formatter/text_spec.rb +37 -0
  92. data/spec/unit/formatter_spec.rb +46 -0
  93. data/spec/unit/resolver/body_spec.rb +65 -0
  94. data/spec/unit/resolver/format_spec.rb +66 -0
  95. data/spec/unit/resolver/headers_spec.rb +93 -0
  96. data/spec/unit/resolver/http_method_spec.rb +67 -0
  97. data/spec/unit/resolver/middleware_spec.rb +83 -0
  98. data/spec/unit/resolver/query_spec.rb +85 -0
  99. data/spec/unit/resolver/request_spec.rb +121 -0
  100. data/spec/unit/resolver/response_spec.rb +64 -0
  101. data/spec/unit/resolver/security_spec.rb +156 -0
  102. data/spec/unit/resolver/uri_spec.rb +117 -0
  103. data/spec/unit/rspec_spec.rb +342 -0
  104. data/spec/unit/schema/operation_spec.rb +309 -0
  105. data/spec/unit/schema/scope_spec.rb +110 -0
  106. data/spec/unit/schema_spec.rb +157 -0
  107. data/spec/unit/settings/validator_spec.rb +128 -0
  108. data/spec/unit/settings_spec.rb +248 -0
  109. metadata +192 -135
  110. data/docs/base_url.md +0 -38
  111. data/docs/documentation.md +0 -9
  112. data/docs/headers.md +0 -59
  113. data/docs/http_method.md +0 -31
  114. data/docs/model.md +0 -173
  115. data/docs/operation.md +0 -0
  116. data/docs/overview.md +0 -0
  117. data/docs/path.md +0 -48
  118. data/docs/query.md +0 -99
  119. data/docs/responses.md +0 -66
  120. data/docs/security.md +0 -102
  121. data/docs/settings.md +0 -32
  122. data/lib/evil/client/connection/net_http.rb +0 -57
  123. data/lib/evil/client/dsl.rb +0 -127
  124. data/lib/evil/client/dsl/base.rb +0 -26
  125. data/lib/evil/client/dsl/files.rb +0 -37
  126. data/lib/evil/client/dsl/headers.rb +0 -16
  127. data/lib/evil/client/dsl/http_method.rb +0 -24
  128. data/lib/evil/client/dsl/operation.rb +0 -91
  129. data/lib/evil/client/dsl/operations.rb +0 -41
  130. data/lib/evil/client/dsl/path.rb +0 -25
  131. data/lib/evil/client/dsl/query.rb +0 -16
  132. data/lib/evil/client/dsl/response.rb +0 -61
  133. data/lib/evil/client/dsl/responses.rb +0 -29
  134. data/lib/evil/client/dsl/scope.rb +0 -27
  135. data/lib/evil/client/dsl/security.rb +0 -57
  136. data/lib/evil/client/dsl/verifier.rb +0 -35
  137. data/lib/evil/client/middleware.rb +0 -81
  138. data/lib/evil/client/middleware/base.rb +0 -11
  139. data/lib/evil/client/middleware/merge_security.rb +0 -20
  140. data/lib/evil/client/middleware/normalize_headers.rb +0 -17
  141. data/lib/evil/client/middleware/stringify_form.rb +0 -40
  142. data/lib/evil/client/middleware/stringify_json.rb +0 -19
  143. data/lib/evil/client/middleware/stringify_multipart.rb +0 -36
  144. data/lib/evil/client/middleware/stringify_multipart/part.rb +0 -36
  145. data/lib/evil/client/middleware/stringify_query.rb +0 -35
  146. data/lib/evil/client/operation.rb +0 -34
  147. data/lib/evil/client/operation/request.rb +0 -26
  148. data/lib/evil/client/operation/response.rb +0 -39
  149. data/lib/evil/client/operation/response_error.rb +0 -13
  150. data/lib/evil/client/operation/unexpected_response_error.rb +0 -19
  151. data/spec/features/instantiation_spec.rb +0 -68
  152. data/spec/features/middleware_spec.rb +0 -79
  153. data/spec/features/operation_with_documentation_spec.rb +0 -41
  154. data/spec/features/operation_with_files_spec.rb +0 -40
  155. data/spec/features/operation_with_form_body_spec.rb +0 -158
  156. data/spec/features/operation_with_headers_spec.rb +0 -99
  157. data/spec/features/operation_with_http_method_spec.rb +0 -45
  158. data/spec/features/operation_with_json_body_spec.rb +0 -156
  159. data/spec/features/operation_with_nested_responses_spec.rb +0 -95
  160. data/spec/features/operation_with_path_spec.rb +0 -47
  161. data/spec/features/operation_with_query_spec.rb +0 -84
  162. data/spec/features/operation_with_security_spec.rb +0 -228
  163. data/spec/features/scoping_spec.rb +0 -48
  164. data/spec/support/test_client.rb +0 -15
  165. data/spec/unit/evil/client/connection/net_http_spec.rb +0 -38
  166. data/spec/unit/evil/client/dsl/files_spec.rb +0 -37
  167. data/spec/unit/evil/client/dsl/operation_spec.rb +0 -374
  168. data/spec/unit/evil/client/dsl/operations_spec.rb +0 -29
  169. data/spec/unit/evil/client/dsl/scope_spec.rb +0 -32
  170. data/spec/unit/evil/client/dsl/security_spec.rb +0 -135
  171. data/spec/unit/evil/client/middleware/merge_security_spec.rb +0 -32
  172. data/spec/unit/evil/client/middleware/normalize_headers_spec.rb +0 -17
  173. data/spec/unit/evil/client/middleware/stringify_form_spec.rb +0 -63
  174. data/spec/unit/evil/client/middleware/stringify_json_spec.rb +0 -61
  175. data/spec/unit/evil/client/middleware/stringify_multipart/part_spec.rb +0 -59
  176. data/spec/unit/evil/client/middleware/stringify_multipart_spec.rb +0 -62
  177. data/spec/unit/evil/client/middleware/stringify_query_spec.rb +0 -40
  178. data/spec/unit/evil/client/middleware_spec.rb +0 -46
  179. data/spec/unit/evil/client/operation/request_spec.rb +0 -49
  180. data/spec/unit/evil/client/operation/response_spec.rb +0 -63
@@ -0,0 +1,15 @@
1
+ RSpec.describe Evil::Client::DefinitionError, "#message" do
2
+ let(:error) { described_class.new schema, keys, settings, original }
3
+ let(:keys) { [:path] }
4
+ let(:schema) { "Test::Api.users.update" }
5
+ let(:settings) { :my_settings }
6
+ let(:original) { "something got wrong" }
7
+
8
+ subject { error.message }
9
+
10
+ it "builds a proper error message" do
11
+ expect(error.message).to include "failed to resolve path" \
12
+ " from Test::Api.users.update schema" \
13
+ " for my_settings: something got wrong"
14
+ end
15
+ end
@@ -0,0 +1,77 @@
1
+ RSpec.describe Evil::Client::NameError do
2
+ let(:error) { described_class.new name, forbidden }
3
+ let(:name) { "foo" }
4
+ let(:forbidden) { %i[foo bar] }
5
+
6
+ describe ".check!" do
7
+ subject { described_class.check! name, forbidden }
8
+
9
+ context "with a valid name" do
10
+ let(:name) { "qux_3" }
11
+
12
+ it "symbolizes the name" do
13
+ expect(subject).to eq :qux_3
14
+ end
15
+ end
16
+
17
+ context "with a name starting from a digit" do
18
+ let(:name) { "1qux_3" }
19
+
20
+ it "raises itself" do
21
+ expect { subject }.to raise_error described_class
22
+ end
23
+ end
24
+
25
+ context "with a name starting from underscore" do
26
+ let(:name) { "_qux_3" }
27
+
28
+ it "raises itself" do
29
+ expect { subject }.to raise_error described_class
30
+ end
31
+ end
32
+
33
+ context "with a one-letter name" do
34
+ let(:name) { "q" }
35
+
36
+ it "raises itself" do
37
+ expect { subject }.to raise_error described_class
38
+ end
39
+ end
40
+
41
+ context "with a name ending with the underscore" do
42
+ let(:name) { "qux_3_" }
43
+
44
+ it "raises itself" do
45
+ expect { subject }.to raise_error described_class
46
+ end
47
+ end
48
+
49
+ context "with a name containing improper symbols" do
50
+ let(:name) { "quX_3" }
51
+
52
+ it "raises itself" do
53
+ expect { subject }.to raise_error described_class
54
+ end
55
+ end
56
+
57
+ context "with a forbidden name" do
58
+ let(:name) { "foo" }
59
+
60
+ it "raises itself" do
61
+ expect { subject }.to raise_error described_class
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#message" do
67
+ subject { error.message }
68
+
69
+ it "builds a proper error message" do
70
+ expect(subject).to eq "Invalid name :foo." \
71
+ " It should contain latin letters in the lower case," \
72
+ " digits, and underscores only; have minimum 2 chars;" \
73
+ " start from a letter; end with either letter or digit." \
74
+ " The following names: 'foo', 'bar' are already used by Evil::Client."
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,22 @@
1
+ RSpec.describe Evil::Client::ResponseError, "#message" do
2
+ let(:error) { described_class.new schema, settings, response }
3
+ let(:schema) { "Test::Api.users.get" }
4
+ let(:settings) { :my_settings }
5
+ let(:response) { [422, { "Language" => "en" }, ["something has got wrong"]] }
6
+
7
+ subject { error.message }
8
+
9
+ it "builds a proper error message" do
10
+ expect(error.message).to eq "remote API responded to Test::Api.users.get" \
11
+ " with unexpected status 422"
12
+ end
13
+
14
+ it "handles proper data" do
15
+ expect(error.schema).to eq schema
16
+ expect(error.settings).to eq settings
17
+ expect(error.response).to eq response
18
+ expect(error.status).to eq response[0]
19
+ expect(error.headers).to eq response[1]
20
+ expect(error.body).to eq response[2]
21
+ end
22
+ end
@@ -0,0 +1,71 @@
1
+ RSpec.describe Evil::Client::TypeError do
2
+ let(:error) { described_class.new name, type }
3
+
4
+ describe ".check!" do
5
+ subject { described_class.check! schema, name, type }
6
+
7
+ let(:schema) { double operations: { foo: double }, scopes: { bar: double } }
8
+
9
+ context "with unused name" do
10
+ let(:name) { :qux }
11
+ let(:type) { :operation }
12
+
13
+ it { is_expected.to be_nil }
14
+ end
15
+
16
+ context "with valid name for operation" do
17
+ let(:name) { :foo }
18
+ let(:type) { :operation }
19
+
20
+ it { is_expected.to be_nil }
21
+ end
22
+
23
+ context "with valid name for scope" do
24
+ let(:name) { :bar }
25
+ let(:type) { :scope }
26
+
27
+ it { is_expected.to be_nil }
28
+ end
29
+
30
+ context "with invalid name for operation" do
31
+ let(:name) { :bar }
32
+ let(:type) { :operation }
33
+
34
+ it "raises itself" do
35
+ expect { subject }.to raise_error described_class
36
+ end
37
+ end
38
+
39
+ context "with invalid name for scope" do
40
+ let(:name) { :foo }
41
+ let(:type) { :scope }
42
+
43
+ it "raises itself" do
44
+ expect { subject }.to raise_error described_class
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "#message" do
50
+ subject { error.message }
51
+ let(:name) { "foo" }
52
+
53
+ context "for a scope" do
54
+ let(:type) { :scope }
55
+
56
+ it "builds a proper error message" do
57
+ expect(subject).to eq "The operation :foo was already defined." \
58
+ " You cannot create scope with the same name."
59
+ end
60
+ end
61
+
62
+ context "for an operation" do
63
+ let(:type) { :operation }
64
+
65
+ it "builds a proper error message" do
66
+ expect(subject).to eq "The scope :foo was already defined." \
67
+ " You cannot create operation with the same name."
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,13 @@
1
+ RSpec.describe Evil::Client::ValidationError, "#message" do
2
+ let(:error) { described_class.new key, scope, options }
3
+ let(:key) { :token_present }
4
+ let(:scope) { "Test::Api.users.update" }
5
+ let(:options) { { id: 3, name: "Andrew" } }
6
+
7
+ subject { error.message }
8
+
9
+ it "builds a proper error message" do
10
+ # see spec/fixtures/locales/en.yml
11
+ expect(subject).to eq "To update user id:3 you must provide a token"
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ RSpec.describe Evil::Client::Formatter::Form do
2
+ subject { described_class.call value }
3
+
4
+ context "when value is a hash" do
5
+ let(:value) { { foo: { bar: [baz: :qux], qux: [1, 2] } } }
6
+
7
+ it "returns formatted string" do
8
+ expect(subject).to eq "foo[bar][][baz]=qux&foo[qux][]=1&foo[qux][]=2"
9
+ end
10
+ end
11
+
12
+ context "when value is nil" do
13
+ let(:value) { nil }
14
+
15
+ it "returns nil" do
16
+ expect(subject).to be_nil
17
+ end
18
+ end
19
+
20
+ context "when value is not a hash" do
21
+ let(:value) { 844 }
22
+
23
+ it "raises Evil::Client::DefinitionError" do
24
+ expect { subject }.to raise_error StandardError, "844 is not a hash"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ RSpec.describe Evil::Client::Formatter::Multipart do
2
+ subject { described_class.call(*parts, boundary: "foobar") }
3
+
4
+ let(:parts) { [string_io, string] }
5
+ let(:string_io) { StringIO.new "Hola!" }
6
+ let(:string) { "Hello!" }
7
+
8
+ it "converts values to multipart body" do
9
+ expect(subject).to eq \
10
+ "\r\n\r\n" \
11
+ "--foobar\r\n" \
12
+ "Content-Disposition: form-data; name=\"Part1\"\r\n" \
13
+ "Content-Type: text/plain; charset=utf-8\r\n" \
14
+ "\r\n" \
15
+ "Hola!\r\n" \
16
+ "--foobar\r\n" \
17
+ "Content-Disposition: form-data; name=\"Part2\"\r\n" \
18
+ "Content-Type: text/plain; charset=utf-8\r\n" \
19
+ "\r\n" \
20
+ "Hello!\r\n" \
21
+ "--foobar--\r\n"
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ RSpec.describe Evil::Client::Formatter::Part do
2
+ subject { described_class.call(value, 23).encode("utf-8") }
3
+
4
+ context "when value is a file" do
5
+ let(:value) do
6
+ Tempfile.new(%w[hello .xml], encoding: "ascii-8bit").tap do |f|
7
+ f.write "Hi!"
8
+ f.rewind
9
+ end
10
+ end
11
+
12
+ it "converts the value to a part of multipart body" do
13
+ [
14
+ "Content-Disposition: form-data; name=\"hello",
15
+ "Content-Type: application/xml; charset=ascii-8bit",
16
+ "Hi!"
17
+ ].each { |str| expect(subject).to include str }
18
+ end
19
+
20
+ after do
21
+ value.close
22
+ value.unlink
23
+ end
24
+ end
25
+
26
+ context "when value is a StringIO" do
27
+ let(:value) { StringIO.new "Упс!".force_encoding "windows-1251" }
28
+
29
+ it "converts the value to a part of multipart body" do
30
+ [
31
+ "Content-Disposition: form-data; name=\"Part23\"",
32
+ "Content-Type: text/plain; charset=windows-1251",
33
+ "РЈРїСЃ!"
34
+ ].each { |str| expect(subject).to include str }
35
+ end
36
+ end
37
+
38
+ context "when value is a string" do
39
+ let(:value) { "Hi!" }
40
+
41
+ it "converts the value to a part of multipart body" do
42
+ [
43
+ "Content-Disposition: form-data; name=\"Part23\"",
44
+ "Content-Type: text/plain; charset=utf-8",
45
+ "Hi!"
46
+ ].each { |str| expect(subject).to include str }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,37 @@
1
+ RSpec.describe Evil::Client::Formatter::Text do
2
+ subject { described_class.call(source) }
3
+
4
+ context "from file" do
5
+ let(:source) do
6
+ Tempfile.new(%w[hello .xml], encoding: "ascii-8bit").tap do |f|
7
+ f.write "Hi!"
8
+ f.rewind
9
+ end
10
+ end
11
+
12
+ it "reads the file" do
13
+ expect(subject).to eq "Hi!"
14
+ end
15
+
16
+ after do
17
+ source.close
18
+ source.unlink
19
+ end
20
+ end
21
+
22
+ context "from a StringIO" do
23
+ let(:source) { StringIO.new "Hello!" }
24
+
25
+ it "reads the IO" do
26
+ expect(subject).to eq "Hello!"
27
+ end
28
+ end
29
+
30
+ context "from another source" do
31
+ let(:source) { %i[2384] }
32
+
33
+ it "stringifies the source" do
34
+ expect(subject).to eq '[:"2384"]'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ RSpec.describe Evil::Client::Formatter do
2
+ subject { described_class.call source, format, boundary: "foobar" }
3
+
4
+ let(:source) { { foo: :bar } }
5
+
6
+ context "for :json format" do
7
+ let(:format) { :json }
8
+
9
+ it "returns formatted body as json" do
10
+ expect(subject).to eq '{"foo":"bar"}'
11
+ end
12
+ end
13
+
14
+ context "for :yaml format" do
15
+ let(:format) { :yaml }
16
+
17
+ it "returns formatted body as yaml" do
18
+ expect(subject).to eq "---\n:foo: :bar\n"
19
+ end
20
+ end
21
+
22
+ context "for :text format" do
23
+ let(:format) { :text }
24
+
25
+ it "returns formatted body as plain text" do
26
+ expect(subject).to eq "{:foo=>:bar}"
27
+ end
28
+ end
29
+
30
+ context "for :form format" do
31
+ let(:format) { :form }
32
+
33
+ it "returns formatted body as form/urlencoded" do
34
+ expect(subject).to eq "foo=bar"
35
+ end
36
+ end
37
+
38
+ context "for :multipart format" do
39
+ let(:format) { :multipart }
40
+
41
+ it "returns formatted body as a multipart" do
42
+ expect(subject).to include "--foobar"
43
+ expect(subject).to include "foo=bar"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,65 @@
1
+ RSpec.describe Evil::Client::Resolver::Body, ".call" do
2
+ subject { described_class.call schema, settings }
3
+
4
+ let(:log) { StringIO.new }
5
+ let(:logger) { Logger.new log }
6
+ let(:settings) { double :my_settings, version: 77, logger: logger }
7
+
8
+ let(:root_schema) do
9
+ double :my_parent_schema,
10
+ definitions: { body: proc { %W[v#{version}] } },
11
+ parent: nil
12
+ end
13
+
14
+ let(:schema) do
15
+ double :my_schema,
16
+ definitions: { body: proc { { version: "v#{version}" } } },
17
+ parent: root_schema
18
+ end
19
+
20
+ it "resolves body from a schema" do
21
+ expect(subject).to eq version: "v77"
22
+ end
23
+
24
+ it "logs the result" do
25
+ subject
26
+
27
+ expect(log.string).to include described_class.name
28
+ expect(log.string).to include "my_schema"
29
+ expect(log.string).to include "my_settings"
30
+ expect(log.string).to include "v77"
31
+ end
32
+
33
+ context "when logger level was set to INFO" do
34
+ before { logger.level = Logger::INFO }
35
+
36
+ it "skips logging" do
37
+ expect { subject }.not_to change { log.string }
38
+ end
39
+ end
40
+
41
+ context "when current schema not defines a body" do
42
+ before { schema.definitions.delete :body }
43
+
44
+ it "resolves body from a parent schema" do
45
+ expect(subject).to eq %w[v77]
46
+ end
47
+ end
48
+
49
+ context "when root body definitions was reloaded by nil" do
50
+ before { schema.definitions[:body] = proc {} }
51
+
52
+ it "resolves body to nil" do
53
+ expect(subject).to be_nil
54
+ end
55
+ end
56
+
57
+ context "when body not defined by any schema" do
58
+ before { schema.definitions.delete :body }
59
+ before { root_schema.definitions.delete :body }
60
+
61
+ it "resolves body to nil" do
62
+ expect(subject).to be_nil
63
+ end
64
+ end
65
+ end