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
@@ -1,95 +0,0 @@
1
- RSpec.describe "operation with nested responses" do
2
- # see Test::Client definition in `/spec/support/test_client.rb`
3
- before do
4
- class Test::User < Evil::Struct
5
- attribute :name
6
- end
7
-
8
- class Test::Client < Evil::Client
9
- operation do
10
- http_method :get
11
- path { "users" }
12
-
13
- response :success, 200, format: :plain
14
- end
15
-
16
- operation :example do
17
- responses format: :plain do
18
- response :created, 201 do |body|
19
- body.to_sym
20
- end
21
-
22
- responses raise: true do
23
- response :not_found, 404
24
-
25
- response :error, 422 do |body|
26
- body.to_sym
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- let(:client) { Test::Client.new "foo", user: "bar", version: 3, token: "baz" }
35
-
36
- subject { client.operations[:example].call }
37
-
38
- it "takes default setting" do
39
- stub_request(:get, //).to_return status: 200,
40
- headers: { "Foo" => "BAR" },
41
- body: "Hi!"
42
-
43
- expect(subject).to eq "Hi!"
44
- end
45
-
46
- it "applies block to coerce data" do
47
- stub_request(:get, //).to_return status: 201,
48
- headers: { "Foo" => "BAR" },
49
- body: "Hi!"
50
-
51
- expect(subject).to eq :Hi!
52
- end
53
-
54
- it "raises ResponseError when necessary" do
55
- stub_request(:get, //).to_return status: 404,
56
- headers: { "Foo" => "BAR" },
57
- body: "Hi!"
58
-
59
- begin
60
- subject
61
- rescue Evil::Client::Operation::ResponseError => error
62
- expect(error.data).to eq "Hi!"
63
- else
64
- raise
65
- end
66
- end
67
-
68
- it "can raise ResponseError with coercion" do
69
- stub_request(:get, //).to_return status: 422,
70
- headers: { "Foo" => "BAR" },
71
- body: "Hi!"
72
-
73
- begin
74
- subject
75
- rescue Evil::Client::Operation::ResponseError => error
76
- expect(error.data).to eq :Hi!
77
- else
78
- raise
79
- end
80
- end
81
-
82
- it "raises UnexpectedResponseError when a status not expected" do
83
- stub_request(:get, //).to_return status: 400,
84
- headers: { "Foo" => "BAR" },
85
- body: "Hi!"
86
-
87
- begin
88
- subject
89
- rescue Evil::Client::Operation::UnexpectedResponseError => error
90
- expect(error.data).to eq "Hi!"
91
- else
92
- raise
93
- end
94
- end
95
- end
@@ -1,47 +0,0 @@
1
- RSpec.describe "operation with path" do
2
- # see Test::Client definition in `/spec/support/test_client.rb`
3
- before do
4
- class Test::Client < Evil::Client
5
- operation do
6
- http_method :get
7
- path "users"
8
- response :success, 200
9
- end
10
-
11
- operation :find_users
12
-
13
- operation :find_user do
14
- path { |id:, **| "users/#{id}" }
15
- end
16
-
17
- operation :login do |settings|
18
- path "login/#{settings.token}"
19
- end
20
- end
21
-
22
- stub_request :get, //
23
- end
24
-
25
- let(:client) { Test::Client.new "foo", user: "bar", version: 3, token: "baz" }
26
-
27
- it "uses default path" do
28
- client.operations[:find_users].call
29
-
30
- expect(a_request(:get, "https://foo.example.com/api/v3/users"))
31
- .to have_been_made
32
- end
33
-
34
- it "uses request options" do
35
- client.operations[:find_user].call(id: 42)
36
-
37
- expect(a_request(:get, "https://foo.example.com/api/v3/users/42"))
38
- .to have_been_made
39
- end
40
-
41
- it "uses settings" do
42
- client.operations[:login].call
43
-
44
- expect(a_request(:get, "https://foo.example.com/api/v3/login/baz"))
45
- .to have_been_made
46
- end
47
- end
@@ -1,84 +0,0 @@
1
- RSpec.describe "operation with query" do
2
- # see Test::Client definition in `/spec/support/test_client.rb`
3
- before do
4
- class Test::User < Evil::Struct
5
- attribute :name
6
- end
7
-
8
- class Test::Client < Evil::Client
9
- operation do
10
- http_method :get
11
- path { "users" }
12
- response :success, 200
13
- end
14
-
15
- operation :filter do
16
- query do
17
- attribute :age, type: Dry::Types["coercible.int"]
18
- attribute :male, default: proc { true }
19
- attribute :name, optional: true
20
- end
21
- end
22
-
23
- operation :search do
24
- query model: Test::User
25
- end
26
- end
27
-
28
- stub_request(:get, //)
29
- end
30
-
31
- let(:path) { "https://foo.example.com/api/v3/users" }
32
- let(:client) { Test::Client.new "foo", user: "bar", version: 3, token: "baz" }
33
-
34
- it "provides a query from options ordered by name" do
35
- client.operations[:filter].call age: 48, male: false, name: "John"
36
-
37
- expect(a_request(:get, "#{path}?age=48&male=false&name=John"))
38
- .to have_been_made
39
- end
40
-
41
- it "uses http encoding" do
42
- client.operations[:filter].call age: 7, name: "Ян"
43
-
44
- expect(a_request(:get, "#{path}?age=7&male=true&name=%D0%AF%D0%BD"))
45
- .to have_been_made
46
- end
47
-
48
- it "skips unassigned optional attributes" do
49
- client.operations[:filter].call age: 7
50
-
51
- expect(a_request(:get, "#{path}?age=7&male=true")).to have_been_made
52
- end
53
-
54
- it "accepts a model" do
55
- client.operations[:search].call name: "Joe"
56
-
57
- expect(a_request(:get, "#{path}?name=Joe")).to have_been_made
58
- end
59
-
60
- it "ignores unspecified options" do
61
- client.operations[:search].call id: 1, name: "Joe"
62
-
63
- expect(a_request(:get, "#{path}?name=Joe")).to have_been_made
64
- end
65
-
66
- it "applies type restrictuions" do
67
- expect { client.operations[:filter].call id: 1, name: "Joe" }
68
- .to raise_error(ArgumentError)
69
- end
70
-
71
- it "supports nesting in a Rails style" do
72
- client.operations[:search].call name: {
73
- "first": "John", last: "Doe", middle: %w[Juan Andre]
74
- }
75
- query = [
76
- "name%5Bfirst%5D=John",
77
- "name%5Blast%5D=Doe",
78
- "name%5Bmiddle%5D%5B0%5D=Juan",
79
- "name%5Bmiddle%5D%5B1%5D=Andre"
80
- ].join("&")
81
-
82
- expect(a_request(:get, "#{path}?#{query}")).to have_been_made
83
- end
84
- end
@@ -1,228 +0,0 @@
1
- RSpec.describe "operation with security" do
2
- # see Test::Client definition in `/spec/support/test_client.rb`
3
- before do
4
- class Test::Client < Evil::Client
5
- operation do
6
- http_method :get
7
- path { "data" }
8
- response :success, 200
9
- end
10
- end
11
-
12
- stub_request(:get, //)
13
- end
14
-
15
- let(:path) { "https://foo.example.com/api/v3/data" }
16
- let(:client) do
17
- Test::Client.new "foo",
18
- version: 3,
19
- user: "bar",
20
- password: "baz",
21
- token: "qux"
22
- end
23
-
24
- subject { client.operations[:example].call }
25
-
26
- context "without operation-specific settings" do
27
- before do
28
- class Test::Client < Evil::Client
29
- operation do |settings|
30
- http_method :get
31
- path { "data" }
32
- response :success, 200
33
-
34
- security do
35
- basic_auth settings.user, settings.password
36
- end
37
- end
38
-
39
- operation :example
40
- end
41
- end
42
-
43
- it "uses default settings" do
44
- request = a_request(:get, path).with do |req|
45
- expect(req.headers).to include "Authorization" => "Basic YmFyOmJheg=="
46
- end
47
-
48
- subject
49
- expect(request).to have_been_made
50
- end
51
- end
52
-
53
- context "with basic_auth" do
54
- before do
55
- class Test::Client < Evil::Client
56
- operation :example do |settings|
57
- security { basic_auth settings.user, settings.password }
58
- end
59
- end
60
- end
61
-
62
- it "adds header" do
63
- request = a_request(:get, path).with do |req|
64
- expect(req.headers).to include "Authorization" => "Basic YmFyOmJheg=="
65
- end
66
-
67
- subject
68
- expect(request).to have_been_made
69
- end
70
- end
71
-
72
- context "with prefixed token_auth in headers" do
73
- before do
74
- class Test::Client < Evil::Client
75
- operation :example do |settings|
76
- security { token_auth settings.token, prefix: "Bearer" }
77
- end
78
- end
79
- end
80
-
81
- it "adds header" do
82
- request = a_request(:get, path).with do |req|
83
- expect(req.headers).to include "Authorization" => "Bearer qux"
84
- end
85
-
86
- subject
87
- expect(request).to have_been_made
88
- end
89
- end
90
-
91
- context "with token_auth without prefix in headers" do
92
- before do
93
- class Test::Client < Evil::Client
94
- operation :example do |settings|
95
- security { token_auth settings.token }
96
- end
97
- end
98
- end
99
-
100
- it "adds header" do
101
- request = a_request(:get, path).with do |req|
102
- expect(req.headers).to include "Authorization" => "qux"
103
- end
104
-
105
- subject
106
- expect(request).to have_been_made
107
- end
108
- end
109
-
110
- context "with token_auth in query" do
111
- before do
112
- class Test::Client < Evil::Client
113
- operation :example do |settings|
114
- security { token_auth settings.token, using: :query }
115
- end
116
- end
117
- end
118
-
119
- it "adds options to query" do
120
- request = a_request(:get, "#{path}?access_token=qux").with do |req|
121
- expect(req.headers.keys).not_to include "Authorization"
122
- end
123
-
124
- subject
125
- expect(request).to have_been_made
126
- end
127
- end
128
-
129
- context "with token_auth in json body" do
130
- before do
131
- class Test::Client < Evil::Client
132
- operation :example do |settings|
133
- security { token_auth settings.token, using: :body }
134
- body format: "json"
135
- end
136
- end
137
- end
138
-
139
- it "adds options to body" do
140
- request = a_request(:get, path).with do |req|
141
- expect(req.body).to eq '{"access_token":"qux"}'
142
- end
143
-
144
- subject
145
- expect(request).to have_been_made
146
- end
147
- end
148
-
149
- context "with token_auth in a plain(form) body" do
150
- before do
151
- class Test::Client < Evil::Client
152
- operation :example do |settings|
153
- security { token_auth settings.token, using: :body }
154
- body format: "form"
155
- end
156
- end
157
- end
158
-
159
- it "adds options to body" do
160
- request = a_request(:get, path).with do |req|
161
- expect(req.body).to eq "access_token=qux"
162
- end
163
-
164
- subject
165
- expect(request).to have_been_made
166
- end
167
- end
168
-
169
- context "with key_auth in headers" do
170
- before do
171
- class Test::Client < Evil::Client
172
- operation :example do
173
- security { key_auth "fOo", "bAr" }
174
- end
175
- end
176
- end
177
-
178
- it "adds header" do
179
- request = a_request(:get, path).with do |req|
180
- expect(req.headers).to include "Foo" => "bAr"
181
- end
182
-
183
- subject
184
- expect(request).to have_been_made
185
- end
186
- end
187
-
188
- context "with key_auth in query" do
189
- before do
190
- class Test::Client < Evil::Client
191
- operation :example do |_settings|
192
- security { key_auth :fOo, :bAr, using: :query }
193
- end
194
- end
195
- end
196
-
197
- it "adds options to query" do
198
- request = a_request(:get, "#{path}?fOo=bAr")
199
-
200
- subject
201
- expect(request).to have_been_made
202
- end
203
- end
204
-
205
- context "with several methods at once" do
206
- before do
207
- class Test::Client < Evil::Client
208
- operation :example do |_settings|
209
- security do
210
- key_auth "foo", "bar", using: :query
211
- key_auth "baz", "qux"
212
- basic_auth "foo", "bar"
213
- end
214
- end
215
- end
216
- end
217
-
218
- it "combines definitions" do
219
- request = a_request(:get, "#{path}?foo=bar").with do |req|
220
- expect(req.headers).to include "Authorization" => "Basic Zm9vOmJhcg==",
221
- "Baz" => "qux"
222
- end
223
-
224
- subject
225
- expect(request).to have_been_made
226
- end
227
- end
228
- end