create_tests 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/lib/create-tests/create_test.rb +76 -8
- data/lib/create-tests/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4ca29473a6da1f495ae3bb61fc97638c049f03a7e7093f54db1ac5a1e602b97b
|
|
4
|
+
data.tar.gz: 829f1a5085c49bc9339095d6fbb9d6f603f6badaa0691f9344e8c0f173ca58f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 99a571060b7ab3971fff6ee6b0e8c67db21df52cc0ae00dbc57da0a26517aa94c8b63e8e606926bccb07a83c7d92e5f2a639495daf0c530f6bc6fe5b2189abfb
|
|
7
|
+
data.tar.gz: 785a8211a25f007e77b961868208081065b0f04e4d962382aa4b644acb757a6f6fc37b9c48e06b032e637906dcebac7127fabdfb0599a44e2719d65811bb7a3d
|
data/README.md
CHANGED
|
@@ -75,7 +75,7 @@ CreateTests.from "./requests/uber.yaml.rb"
|
|
|
75
75
|
|
|
76
76
|
For each API endpoint, `create_tests` generates up to 7 test types:
|
|
77
77
|
|
|
78
|
-
1. **"has correct structure in successful response"** -- Calls the endpoint and validates the response structure using `NiceHttp.validate_response` with diff details on failure.
|
|
78
|
+
1. **"has correct structure in successful response"** -- Calls the endpoint and validates the response structure using `NiceHttp.validate_response` with diff details on failure. The expected status is the first 2xx response key, else `default`, else the first key. When `:data_default` is present, missing (or nil) keys in `:data` are filled before the call; existing example values are not overwritten.
|
|
79
79
|
|
|
80
80
|
2. **"doesn't retrieve data if not authenticated"** -- Calls with empty headers and asserts a 4xx response.
|
|
81
81
|
|
|
@@ -85,9 +85,9 @@ For each API endpoint, `create_tests` generates up to 7 test types:
|
|
|
85
85
|
|
|
86
86
|
5. **"handles multiple valid data variations"** -- For POST/PUT/PATCH endpoints with a payload source, uses `generate_n(5, :correct)` from nice_hash to test 5 different valid payload variations. Prefers `:data_pattern` when present (real string_pattern / enum / range values from open_api_import); otherwise uses `:data`. Generated values are assigned to `request[:data]` before the call.
|
|
87
87
|
|
|
88
|
-
6. **"returns error when individual data fields are invalid"** -- Uses `NiceHash.change_one_by_one` on `:data_pattern` (preferred) or `:data` to systematically test each field being wrong one at a time, asserting the server rejects each one.
|
|
88
|
+
6. **"returns error when individual data fields are invalid"** -- Uses `NiceHash.change_one_by_one` on `:data_pattern` (preferred) or `:data` to systematically test each field being wrong one at a time, asserting the server rejects each one. Fields listed in `:data_read_only` are skipped.
|
|
89
89
|
|
|
90
|
-
7. **"returns error if required parameter on data empty/missing"** -- For endpoints with `data_required`, tests both empty and missing values for each required data field. When `:data` is absent but `:data_examples` is present (common for form uploads), the first example is used as the body for success and required-data tests.
|
|
90
|
+
7. **"returns error if required parameter on data empty/missing"** -- For endpoints with `data_required`, tests both empty and missing values for each required data field. When `:data` is absent but `:data_examples` is present (common for form uploads), the first example is used as the body for success and required-data tests. Otherwise `:data_default` can seed missing body fields the same way as the success example.
|
|
91
91
|
|
|
92
92
|
Required keyword parameters from open_api_import `create_constants: true` (e.g. `def self.get_item(id: ID)`) get Helper stubs and are called as keywords (`id: @id`), same as positional required args.
|
|
93
93
|
|
|
@@ -149,6 +149,16 @@ class CreateTests
|
|
|
149
149
|
has_data_examples = request.key?(:data_examples) &&
|
|
150
150
|
request[:data_examples].is_a?(Array) &&
|
|
151
151
|
!request[:data_examples].empty?
|
|
152
|
+
has_data_default = request.key?(:data_default) &&
|
|
153
|
+
request[:data_default].is_a?(Hash) &&
|
|
154
|
+
!request[:data_default].empty?
|
|
155
|
+
# Prefer data_examples over defaults when :data is absent
|
|
156
|
+
apply_data_default = has_data_default && (request.key?(:data) || !has_data_examples)
|
|
157
|
+
apply_defaults_txt = if apply_data_default
|
|
158
|
+
"@request[:data] ||= {}\n @request[:data_default].each do |k, v|\n @request[:data][k] = v if !@request[:data].key?(k) || @request[:data][k].nil?\n end\n "
|
|
159
|
+
else
|
|
160
|
+
""
|
|
161
|
+
end
|
|
152
162
|
# Prefer data_pattern for variation/invalid-field tests; fall back to :data
|
|
153
163
|
payload_source = if request.key?(:data_pattern)
|
|
154
164
|
":data_pattern"
|
|
@@ -156,16 +166,17 @@ class CreateTests
|
|
|
156
166
|
":data"
|
|
157
167
|
end
|
|
158
168
|
|
|
159
|
-
#
|
|
169
|
+
# Success code: first 2xx key, else "default", else first key
|
|
160
170
|
if include_kind?(only_kinds, :success) && request.key?(:responses) and request[:responses].size > 0
|
|
161
|
-
code = request[:responses]
|
|
171
|
+
code = success_response_code(request[:responses])
|
|
172
|
+
code_src = format_response_code(code)
|
|
162
173
|
title = example_title("has correct structure in successful response", test, trailing_space: true)
|
|
163
174
|
if !request.key?(:data) && has_data_examples
|
|
164
175
|
tests[title] = "do
|
|
165
176
|
request = @request.deep_copy
|
|
166
177
|
request[:data] = @request[:data_examples].first
|
|
167
178
|
resp = @http.#{request[:method]}(request)
|
|
168
|
-
#{assert_eq('resp.code',
|
|
179
|
+
#{assert_eq('resp.code', code_src, test)}\n"
|
|
169
180
|
if request[:responses][code].is_a?(Hash) and request[:responses][code].key?(:data)
|
|
170
181
|
tests[title] +="result = NiceHttp.validate_response(resp, @request.responses._#{code}.data, include_diff: true)\n"
|
|
171
182
|
tests[title] += "#{assert_be_true('result[:ok]', 'Structure mismatch: #{result[:diff]}', test)}\n"
|
|
@@ -173,8 +184,8 @@ class CreateTests
|
|
|
173
184
|
tests[title] += "end\n"
|
|
174
185
|
else
|
|
175
186
|
tests[title] = "do
|
|
176
|
-
resp = @http.#{request[:method]}(@request)
|
|
177
|
-
#{assert_eq('resp.code',
|
|
187
|
+
#{apply_defaults_txt}resp = @http.#{request[:method]}(@request)
|
|
188
|
+
#{assert_eq('resp.code', code_src, test)}\n"
|
|
178
189
|
|
|
179
190
|
if request[:responses][code].is_a?(Hash) and request[:responses][code].key?(:data)
|
|
180
191
|
tests[title] +="result = NiceHttp.validate_response(resp, @request.responses._#{code}.data, include_diff: true)\n"
|
|
@@ -253,8 +264,20 @@ class CreateTests
|
|
|
253
264
|
end
|
|
254
265
|
|
|
255
266
|
if include_kind?(only_kinds, :invalid_fields) && payload_source
|
|
256
|
-
|
|
257
|
-
|
|
267
|
+
payload_key = payload_source == ":data_pattern" ? :data_pattern : :data
|
|
268
|
+
read_only_names = Array(request[:data_read_only]).map(&:to_s)
|
|
269
|
+
payload_for_invalid = request[payload_key]
|
|
270
|
+
if payload_for_invalid.is_a?(Hash) && !read_only_names.empty?
|
|
271
|
+
payload_for_invalid = payload_for_invalid.deep_copy
|
|
272
|
+
read_only_names.each do |name|
|
|
273
|
+
payload_for_invalid.delete(name.to_sym)
|
|
274
|
+
payload_for_invalid.delete(name)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
unless payload_for_invalid.nil? || (payload_for_invalid.respond_to?(:empty?) && payload_for_invalid.empty?)
|
|
278
|
+
title = example_title("returns error when individual data fields are invalid", test, trailing_space: true)
|
|
279
|
+
if read_only_names.empty?
|
|
280
|
+
tests[title] = "do
|
|
258
281
|
wrong = @request[#{payload_source}].generate(:correct, errors: :min_length)
|
|
259
282
|
NiceHash.change_one_by_one([@request[#{payload_source}], :correct], wrong).each do |one_wrong|
|
|
260
283
|
request = @request.deep_copy
|
|
@@ -263,11 +286,32 @@ class CreateTests
|
|
|
263
286
|
#{assert_between('resp.code.to_i', '200', '299', test, negate: true)}
|
|
264
287
|
end
|
|
265
288
|
end\n"
|
|
289
|
+
else
|
|
290
|
+
read_only_lit = request[:data_read_only].map(&:inspect).join(", ")
|
|
291
|
+
tests[title] = "do
|
|
292
|
+
payload = @request[#{payload_source}].deep_copy
|
|
293
|
+
[#{read_only_lit}].each do |f|
|
|
294
|
+
payload.delete(f)
|
|
295
|
+
payload.delete(f.to_s)
|
|
296
|
+
payload.delete(f.to_s.to_sym)
|
|
297
|
+
end
|
|
298
|
+
wrong = payload.generate(:correct, errors: :min_length)
|
|
299
|
+
NiceHash.change_one_by_one([payload, :correct], wrong).each do |one_wrong|
|
|
300
|
+
request = @request.deep_copy
|
|
301
|
+
request[:data] = one_wrong
|
|
302
|
+
resp = @http.#{request[:method]}(request)
|
|
303
|
+
#{assert_between('resp.code.to_i', '200', '299', test, negate: true)}
|
|
304
|
+
end
|
|
305
|
+
end\n"
|
|
306
|
+
end
|
|
307
|
+
end
|
|
266
308
|
end
|
|
267
309
|
|
|
268
|
-
if include_kind?(only_kinds, :required_data) && request.key?(:data_required) && (request.key?(:data) || has_data_examples)
|
|
310
|
+
if include_kind?(only_kinds, :required_data) && request.key?(:data_required) && (request.key?(:data) || has_data_examples || apply_data_default)
|
|
269
311
|
seed_data_line = if !request.key?(:data) && has_data_examples
|
|
270
312
|
"request[:data] = request[:data_examples].first\n "
|
|
313
|
+
elsif apply_data_default
|
|
314
|
+
"request[:data] ||= {}\n request[:data_default].each do |k, v|\n request[:data][k] = v if !request[:data].key?(k) || request[:data][k].nil?\n end\n "
|
|
271
315
|
else
|
|
272
316
|
""
|
|
273
317
|
end
|
|
@@ -334,6 +378,30 @@ class CreateTests
|
|
|
334
378
|
return modified, output
|
|
335
379
|
end
|
|
336
380
|
|
|
381
|
+
private def success_response_code(responses)
|
|
382
|
+
keys = responses.keys
|
|
383
|
+
twoxx = keys.find do |k|
|
|
384
|
+
n = k.to_s
|
|
385
|
+
n.match?(/\A\d+\z/) && (200..299).include?(n.to_i)
|
|
386
|
+
end
|
|
387
|
+
return twoxx if twoxx
|
|
388
|
+
|
|
389
|
+
default_key = keys.find { |k| k.to_s == "default" }
|
|
390
|
+
return default_key if default_key
|
|
391
|
+
|
|
392
|
+
keys[0]
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# Numeric status codes stay unquoted (eq 200); non-numeric keys use inspect.
|
|
396
|
+
private def format_response_code(code)
|
|
397
|
+
s = code.to_s
|
|
398
|
+
if s.match?(/\A\d+\z/)
|
|
399
|
+
s
|
|
400
|
+
else
|
|
401
|
+
code.inspect
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
337
405
|
private def normalize_only(only)
|
|
338
406
|
return nil if only.nil?
|
|
339
407
|
list = case only
|
data/lib/create-tests/version.rb
CHANGED