evil-client 0.3.3 → 1.0.0

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