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,64 @@
1
+ RSpec.describe Evil::Client::Resolver::Response, ".call" do
2
+ subject { described_class.call schema, settings, response }
3
+
4
+ let(:log) { StringIO.new }
5
+ let(:logger) { Logger.new log }
6
+ let(:response) { [201, { "Content-Language" => "en" }, ["success"]] }
7
+
8
+ let(:root_schema) do
9
+ double :my_parent_schema,
10
+ definitions: { responses: { 201 => proc { |*args| args } } },
11
+ parent: nil
12
+ end
13
+
14
+ let(:schema) do
15
+ double :my_schema,
16
+ definitions: {
17
+ responses: { 201 => proc { |_, _, body| body.first } }
18
+ },
19
+ parent: root_schema
20
+ end
21
+
22
+ let(:settings) do
23
+ double :my_settings, version: 77, token: "eoiqopr==", id: 43, logger: logger
24
+ end
25
+
26
+ it "applies most recent schema to response" do
27
+ expect(subject).to eq "success"
28
+ end
29
+
30
+ it "logs the result" do
31
+ subject
32
+
33
+ expect(log.string).to include described_class.name
34
+ expect(log.string).to include "my_schema"
35
+ expect(log.string).to include "my_settings"
36
+ expect(log.string).to include "201"
37
+ expect(log.string).to include "success"
38
+ end
39
+
40
+ context "when logger level was set to INFO" do
41
+ before { logger.level = Logger::INFO }
42
+
43
+ it "skips logging" do
44
+ expect { subject }.not_to change { log.string }
45
+ end
46
+ end
47
+
48
+ context "when root definition not reloaded" do
49
+ before { schema.definitions[:responses].delete 201 }
50
+
51
+ it "applies root schema to response" do
52
+ expect(subject).to eq response
53
+ end
54
+ end
55
+
56
+ context "when no definitions was given for the status" do
57
+ let(:response) { [202, { "Content-Language" => "en" }, ["success"]] }
58
+
59
+ it "raises Evil::Client::ResponseError" do
60
+ expect { subject }.to raise_error Evil::Client::ResponseError,
61
+ /202/
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,156 @@
1
+ RSpec.describe Evil::Client::Resolver::Security do
2
+ let(:resolver) { described_class.new schema, settings }
3
+ let(:log) { StringIO.new }
4
+ let(:logger) { Logger.new log }
5
+
6
+ let(:root_schema) do
7
+ double :my_parent_schema,
8
+ definitions: { security: proc { key_auth :token, token } },
9
+ parent: nil
10
+ end
11
+
12
+ let(:schema) do
13
+ double :my_schema,
14
+ definitions: { security: proc { key_auth :user, user } },
15
+ parent: root_schema
16
+ end
17
+
18
+ let(:settings) do
19
+ double :my_settings,
20
+ token: "foobar",
21
+ user: "foo",
22
+ password: "baz",
23
+ logger: logger
24
+ end
25
+
26
+ describe ".call" do
27
+ subject { described_class.call schema, settings }
28
+
29
+ it "resolves security settings from a schema" do
30
+ expect(subject).to eq headers: { "user" => "foo" }
31
+ end
32
+
33
+ it "logs the result" do
34
+ subject
35
+
36
+ expect(log.string).to include described_class.name
37
+ expect(log.string).to include "my_schema"
38
+ expect(log.string).to include "my_settings"
39
+ expect(log.string).to include "foo"
40
+ end
41
+
42
+ context "when logger level was set to INFO" do
43
+ before { logger.level = Logger::INFO }
44
+
45
+ it "skips logging" do
46
+ expect { subject }.not_to change { log.string }
47
+ end
48
+ end
49
+
50
+ context "when current schema not defines security settings" do
51
+ before { schema.definitions.delete :security }
52
+
53
+ it "resolves security settings from a parent schema" do
54
+ expect(subject).to eq headers: { "token" => "foobar" }
55
+ end
56
+ end
57
+
58
+ context "when security settings not defined by any schema" do
59
+ before { schema.definitions.delete :security }
60
+ before { root_schema.definitions.delete :security }
61
+
62
+ it "resolves security settings to nil" do
63
+ expect(subject).to eq({})
64
+ end
65
+ end
66
+
67
+ context "when security settings reloaded by nil" do
68
+ before { schema.definitions[:security] = proc {} }
69
+
70
+ it "resolves security settings to nil" do
71
+ expect(subject).to eq({})
72
+ end
73
+ end
74
+
75
+ context "when security settings resolves to unknown key" do
76
+ before { schema.definitions[:security] = proc { { body: { id: 1 } } } }
77
+
78
+ it "raises Evil::Client::DefinitionError" do
79
+ expect { subject }.to raise_error Evil::Client::DefinitionError,
80
+ /body/
81
+ end
82
+ end
83
+
84
+ context "when security settings resolves to not a hash" do
85
+ before { schema.definitions[:security] = proc { { query: :bar } } }
86
+
87
+ it "raises Evil::Client::DefinitionError" do
88
+ expect { subject }.to raise_error Evil::Client::DefinitionError,
89
+ /bar/
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "#key_auth" do
95
+ let(:key) { "foo" }
96
+ let(:value) { "bar" }
97
+ let(:opts) { {} }
98
+
99
+ subject { resolver.key_auth key, value, **opts }
100
+
101
+ it "builds in-headers schema" do
102
+ expect(subject).to eq headers: { "foo" => "bar" }
103
+ end
104
+
105
+ context "when :inside was set to :query" do
106
+ let(:opts) { { inside: :query } }
107
+
108
+ it "builds in-query schema" do
109
+ expect(subject).to eq query: { "foo" => "bar" }
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "#token_auth" do
115
+ let(:value) { "foobar" }
116
+ let(:opts) { {} }
117
+
118
+ subject { resolver.token_auth value, **opts }
119
+
120
+ it "builds default in-headers schema for Authorization" do
121
+ expect(subject).to eq headers: { "Authorization" => "foobar" }
122
+ end
123
+
124
+ context "when :prefix was set" do
125
+ let(:opts) { { prefix: "bearer" } }
126
+
127
+ it "builds prefixed in-headers schema" do
128
+ expect(subject).to eq headers: { "Authorization" => "Bearer foobar" }
129
+ end
130
+ end
131
+
132
+ context "when :inside was set to :query" do
133
+ let(:opts) { { inside: :query } }
134
+
135
+ it "builds default in-query schema for access_token" do
136
+ expect(subject).to eq query: { "access_token" => "foobar" }
137
+ end
138
+
139
+ context "when :prefix was set" do
140
+ let(:opts) { { inside: :query, prefix: "bearer" } }
141
+
142
+ it "ignores prefix in a query" do
143
+ expect(subject).to eq query: { "access_token" => "foobar" }
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ describe "#basic_auth" do
150
+ subject { resolver.basic_auth "foo", "bar" }
151
+
152
+ it "builds basic Authorization schema" do
153
+ expect(subject).to eq headers: { "Authorization" => "Basic Zm9vOmJhcg==" }
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,117 @@
1
+ RSpec.describe Evil::Client::Resolver::Uri, ".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, id: 42, logger: logger }
7
+
8
+ let(:root_schema) do
9
+ double :my_parent_schema,
10
+ definitions: { path: proc { "https://my_api.com/v#{version}" } },
11
+ parent: nil
12
+ end
13
+
14
+ let(:schema) do
15
+ double :my_schema,
16
+ definitions: { path: proc { "/users/#{id}" } },
17
+ parent: root_schema
18
+ end
19
+
20
+ it "resolves uri from a schema" do
21
+ expect(subject).to eq URI("https://my_api.com/v77/users/42")
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 "https://my_api.com/v77/users/42"
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 an uri" do
42
+ before { schema.definitions.delete :path }
43
+
44
+ it "resolves uri from a parent schema" do
45
+ expect(subject).to eq URI("https://my_api.com/v77")
46
+ end
47
+ end
48
+
49
+ context "when path was defined with errors" do
50
+ before { root_schema.definitions.delete :path }
51
+
52
+ it "raises StandardError" do
53
+ expect { subject }.to raise_error StandardError
54
+ end
55
+
56
+ it "logs the result" do
57
+ subject rescue nil
58
+
59
+ expect(log.string).to include described_class.name
60
+ expect(log.string).to include "my_schema"
61
+ expect(log.string).to include "my_settings"
62
+ end
63
+ end
64
+
65
+ context "when uri cannot be resolved" do
66
+ let(:settings) { double :my_settings, version: 1, logger: logger }
67
+
68
+ it "raises StandardError" do
69
+ expect { subject }.to raise_error StandardError
70
+ end
71
+
72
+ it "logs the result" do
73
+ subject rescue nil
74
+
75
+ expect(log.string).to include described_class.name
76
+ expect(log.string).to include "my_schema"
77
+ expect(log.string).to include "my_settings"
78
+ end
79
+ end
80
+
81
+ context "when path wasn't defined" do
82
+ before { root_schema.definitions.delete :path }
83
+ before { schema.definitions.delete :path }
84
+
85
+ it "raises Evil::Client::DefinitionError" do
86
+ expect { subject }
87
+ .to raise_error Evil::Client::DefinitionError,
88
+ /base url should be defined/
89
+ end
90
+
91
+ it "logs the result" do
92
+ subject rescue nil
93
+
94
+ expect(log.string).to include described_class.name
95
+ expect(log.string).to include "my_schema"
96
+ expect(log.string).to include "my_settings"
97
+ end
98
+ end
99
+
100
+ context "when uri has a wrong schema" do
101
+ before { root_schema.definitions[:path] = proc { "ws://github.com" } }
102
+
103
+ it "raises Evil::Client::DefinitionError" do
104
+ expect { subject }
105
+ .to raise_error Evil::Client::DefinitionError,
106
+ /base url should use HTTP\(S\). 'ws' used instead/
107
+ end
108
+
109
+ it "logs the result" do
110
+ subject rescue nil
111
+
112
+ expect(log.string).to include described_class.name
113
+ expect(log.string).to include "my_schema"
114
+ expect(log.string).to include "my_settings"
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,342 @@
1
+ RSpec.describe "rspec matcher :perform_operation" do
2
+ before { load "spec/fixtures/test_client.rb" }
3
+
4
+ let(:client) { Test::Client.new(subdomain: "foo", user: "bar", token: "baz") }
5
+ let(:users) { client.crm(version: 7).users }
6
+
7
+ let(:fetch) { users.fetch id: 5 }
8
+ let(:update_7) { users.update id: 5, name: "Joe", language: "en" }
9
+ let(:update_8) { users.update id: 5, name: "Joe", language: "en", version: 8 }
10
+
11
+ let(:name) { "Test::Client.crm.users.update" }
12
+ let(:block) { proc { |version:, **| version == 7 } }
13
+
14
+ describe "base matcher" do
15
+ context "in a positive check" do
16
+ subject { expect { code }.to perform_operation(name) }
17
+
18
+ context "when operaton with expected name was performed" do
19
+ let(:code) { fetch; update_7 }
20
+
21
+ it "passes" do
22
+ expect { subject }.not_to raise_error
23
+ end
24
+ end
25
+
26
+ context "when operation with expected name wasn't performed" do
27
+ let(:code) { fetch }
28
+
29
+ it "fails" do
30
+ expect { subject }
31
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
32
+ end
33
+ end
34
+ end
35
+
36
+ context "in a negative check" do
37
+ subject { expect { code }.not_to perform_operation(name) }
38
+
39
+ context "when operaton with expected name was performed" do
40
+ let(:code) { fetch; update_7 }
41
+
42
+ it "fails" do
43
+ expect { subject }
44
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
45
+ end
46
+ end
47
+
48
+ context "when operation with expected name wasn't performed" do
49
+ let(:code) { fetch }
50
+
51
+ it "passes" do
52
+ expect { subject }.not_to raise_error
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "block argument" do
59
+ context "in a positive check" do
60
+ subject { expect { code }.to perform_operation(name, &block) }
61
+
62
+ context "when operaton with expected name/options was performed" do
63
+ let(:code) { fetch; update_7 }
64
+
65
+ it "passes" do
66
+ expect { subject }.not_to raise_error
67
+ end
68
+ end
69
+
70
+ context "when options differ from expected" do
71
+ let(:code) { fetch; update_8 }
72
+
73
+ it "fails" do
74
+ expect { subject }
75
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
76
+ end
77
+ end
78
+
79
+ context "when operation wasn't performed" do
80
+ let(:code) { fetch }
81
+
82
+ it "fails" do
83
+ expect { subject }
84
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
85
+ end
86
+ end
87
+ end
88
+
89
+ context "in a negagive check" do
90
+ subject { expect { code }.not_to perform_operation(name, &block) }
91
+
92
+ context "when operaton with expected name/options was performed" do
93
+ let(:code) { fetch; update_7 }
94
+
95
+ it "fails" do
96
+ expect { subject }
97
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
98
+ end
99
+ end
100
+
101
+ context "when options differ from expected" do
102
+ let(:code) { fetch; update_8 }
103
+
104
+ it "passes" do
105
+ expect { subject }.not_to raise_error
106
+ end
107
+ end
108
+
109
+ context "when operation wasn't performed" do
110
+ let(:code) { fetch }
111
+
112
+ it "passes" do
113
+ expect { subject }.not_to raise_error
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ describe "#with modifier" do
120
+ let(:opts) { { version: 7 } }
121
+
122
+ context "in a positive check" do
123
+ subject { expect { code }.to perform_operation(name).with(opts) }
124
+
125
+ context "when operaton with expected name/options was performed" do
126
+ let(:code) { fetch; update_7 }
127
+
128
+ it "passes" do
129
+ expect { subject }.not_to raise_error
130
+ end
131
+ end
132
+
133
+ context "when options differ from expected" do
134
+ let(:code) { fetch; update_8 }
135
+
136
+ it "fails" do
137
+ expect { subject }
138
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
139
+ end
140
+ end
141
+
142
+ context "when operation wasn't performed" do
143
+ let(:code) { fetch }
144
+
145
+ it "fails" do
146
+ expect { subject }
147
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
148
+ end
149
+ end
150
+ end
151
+
152
+ context "in a negative check" do
153
+ subject { expect { code }.not_to perform_operation(name).with(opts) }
154
+
155
+ context "when operaton with expected name/options was performed" do
156
+ let(:code) { fetch; update_7 }
157
+
158
+ it "fails" do
159
+ expect { subject }
160
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
161
+ end
162
+ end
163
+
164
+ context "when options differ from expected" do
165
+ let(:code) { fetch; update_8 }
166
+
167
+ it "passes" do
168
+ expect { subject }.not_to raise_error
169
+ end
170
+ end
171
+
172
+ context "when operation wasn't performed" do
173
+ let(:code) { fetch }
174
+
175
+ it "passes" do
176
+ expect { subject }.not_to raise_error
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "#with_exactly modifier" do
183
+ let(:opts) do
184
+ {
185
+ id: 5,
186
+ language: "en",
187
+ name: "Joe",
188
+ subdomain: "foo",
189
+ token: "baz",
190
+ user: "bar",
191
+ version: 7
192
+ }
193
+ end
194
+
195
+ context "in a positive check" do
196
+ subject { expect { code }.to perform_operation(name).with_exactly(opts) }
197
+
198
+ context "when operaton with expected name/options was performed" do
199
+ let(:code) { fetch; update_7 }
200
+
201
+ it "passes" do
202
+ expect { subject }.not_to raise_error
203
+ end
204
+ end
205
+
206
+ context "when some options differ from expected" do
207
+ let(:code) { fetch; update_8 }
208
+
209
+ it "fails" do
210
+ expect { subject }
211
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
212
+ end
213
+ end
214
+
215
+ context "when some options are not expected" do
216
+ before { opts.delete :version }
217
+ let(:code) { fetch; update_7 }
218
+
219
+ it "fails" do
220
+ expect { subject }
221
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
222
+ end
223
+ end
224
+
225
+ context "when operation wasn't performed" do
226
+ let(:code) { fetch }
227
+
228
+ it "fails" do
229
+ expect { subject }
230
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
231
+ end
232
+ end
233
+ end
234
+
235
+ context "in a negative check" do
236
+ subject do
237
+ expect { code }.not_to perform_operation(name).with_exactly(opts)
238
+ end
239
+
240
+ context "when operaton with expected name/options was performed" do
241
+ let(:code) { fetch; update_7 }
242
+
243
+ it "fails" do
244
+ expect { subject }
245
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
246
+ end
247
+ end
248
+
249
+ context "when some options differ from expected" do
250
+ let(:code) { fetch; update_8 }
251
+
252
+ it "passes" do
253
+ expect { subject }.not_to raise_error
254
+ end
255
+ end
256
+
257
+ context "when some options are not expected" do
258
+ before { opts.delete :version }
259
+ let(:code) { fetch; update_7 }
260
+
261
+ it "passes" do
262
+ expect { subject }.not_to raise_error
263
+ end
264
+ end
265
+
266
+ context "when operation wasn't performed" do
267
+ let(:code) { fetch }
268
+
269
+ it "passes" do
270
+ expect { subject }.not_to raise_error
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ describe "#without modifier" do
277
+ context "in a positive check" do
278
+ subject { expect { code }.to perform_operation(name).without(opts) }
279
+
280
+ context "when operaton without options was performed" do
281
+ let(:opts) { %i[phone] }
282
+ let(:code) { fetch; update_7 }
283
+
284
+ it "passes" do
285
+ expect { subject }.not_to raise_error
286
+ end
287
+ end
288
+
289
+ context "when operation contains a forbidden option" do
290
+ let(:opts) { %i[id] }
291
+ let(:code) { fetch; update_7 }
292
+
293
+ it "fails" do
294
+ expect { subject }
295
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
296
+ end
297
+ end
298
+
299
+ context "when operation wasn't performed" do
300
+ let(:opts) { %i[phone] }
301
+ let(:code) { fetch }
302
+
303
+ it "fails" do
304
+ expect { subject }
305
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
306
+ end
307
+ end
308
+ end
309
+
310
+ context "in a negative check" do
311
+ subject { expect { code }.not_to perform_operation(name).without(opts) }
312
+
313
+ context "when operaton without options was performed" do
314
+ let(:opts) { %i[phone] }
315
+ let(:code) { fetch; update_7 }
316
+
317
+ it "fails" do
318
+ expect { subject }
319
+ .to raise_error RSpec::Expectations::ExpectationNotMetError
320
+ end
321
+ end
322
+
323
+ context "when operation contains a forbidden option" do
324
+ let(:opts) { %i[id] }
325
+ let(:code) { fetch; update_7 }
326
+
327
+ it "passes" do
328
+ expect { subject }.not_to raise_error
329
+ end
330
+ end
331
+
332
+ context "when operation wasn't performed" do
333
+ let(:opts) { %i[phone] }
334
+ let(:code) { fetch }
335
+
336
+ it "passes" do
337
+ expect { subject }.not_to raise_error
338
+ end
339
+ end
340
+ end
341
+ end
342
+ end