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,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