@schwabyio/gta 0.11.0 → 0.13.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.
package/README.md CHANGED
@@ -159,6 +159,10 @@ every key, and every rule that makes a file invalid. It is written for people an
159
159
  agents alike, and ends with a complete project to start from. It also ships in this
160
160
  package as `dist/SPEC.md`, and `gta`'s messages cite its sections, as in "(SPEC.md §2.5)".
161
161
 
162
+ [FUNCTIONS.md](https://github.com/schwabyio/gravity/blob/main/FUNCTIONS.md) documents every
163
+ `gta` function that `tests` and `before.script` can call, with examples. It ships as
164
+ `dist/FUNCTIONS.md`.
165
+
162
166
  ## License
163
167
 
164
168
  MIT. The packages bundled into `gta` keep their own licenses, collected in
@@ -0,0 +1,560 @@
1
+ # The `gta` functions
2
+
3
+ Code in a collection runs in two places: `before.script`, before a request is sent, and
4
+ `tests`, after its response arrives. Both have a `gta` object, with nothing to import or
5
+ load. This document lists every function on it.
6
+
7
+ ```yaml
8
+ - name: get user
9
+ GET: '{{baseUrl}}/users/7'
10
+ before:
11
+ script: |
12
+ gta.set('traceId', gta.uuidv7())
13
+ tests: |
14
+ gta.expectResponseStatusCodeToBe(200)
15
+ gta.expectResponseBodyToHaveProperty('user.name', 'Ada')
16
+ gta.expectResponseBodyToHaveProperty('user.email', 'userEmail', 'setAsCollectionVariable')
17
+ ```
18
+
19
+ [SPEC.md](./SPEC.md) specifies the files this code lives in. §5 there covers where code
20
+ goes, the order it runs in, and the other globals: `res`, `req`, `assert`, `params`,
21
+ `endpoint` and `checks`.
22
+
23
+ ---
24
+
25
+ ## At a glance
26
+
27
+ | Function | What it does | `tests` | `before.script` |
28
+ | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | :-----: | :-------------: |
29
+ | [`expectResponseStatusCodeToBe`](#gtaexpectresponsestatuscodetobe) | Check the status code | ✓ | |
30
+ | [`expectResponseToHaveHeader`](#gtaexpectresponsetohaveheader) | Check a header | ✓ | |
31
+ | [`expectResponseBodyToHaveProperty`](#gtaexpectresponsebodytohaveproperty) | Check a property of the body | ✓ | |
32
+ | [`expectResponseBodyToHaveUnorderedArray`](#gtaexpectresponsebodytohaveunorderedarray) | Check an array holds items, in any order | ✓ | |
33
+ | [`expectResponseBodyToHaveUnorderedArrayNotThisItem`](#gtaexpectresponsebodytohaveunorderedarraynotthisitem) | Check an array holds none of some items | ✓ | |
34
+ | [`sortResponseBodyArrays`](#gtasortresponsebodyarrays) | Sort arrays before the checks after it | ✓ | |
35
+ | [`useStrictValidation`](#gtausestrictvalidation) | Fail when any body property goes unchecked | ✓ | |
36
+ | [`ignoreResponseBodyProperty`](#gtaignoreresponsebodyproperty) | Leave a property out of strict validation | ✓ | |
37
+ | [`ignoreResponseBodyArrayObjectProperty`](#gtaignoreresponsebodyarrayobjectproperty) | The same, for a property of every item of an array | ✓ | |
38
+ | [`test`](#gtatest) | A named check of your own | ✓ | |
39
+ | [`get`](#gtaget) | Read a variable | ✓ | ✓ |
40
+ | [`set`](#gtaset) | Set a variable for the steps after | ✓ | ✓ |
41
+ | [`skip`](#gtaskip) | Send nothing for this step | | ✓ |
42
+ | [`skipRest`](#gtaskiprest) | Skip the steps after this one | ✓ | ✓ |
43
+ | [`flag`](#gtaflag) | Read a feature flag | ✓ | ✓ |
44
+ | [`uuid`](#gtauuid) | A random UUID | ✓ | ✓ |
45
+ | [`uuidv7`](#gtauuidv7) | A time-ordered UUID | ✓ | ✓ |
46
+ | [`randomInt`](#gtarandomint) | A random whole number | ✓ | ✓ |
47
+ | [`date`](#gtadate) | A formatted date, now or offset from now | ✓ | ✓ |
48
+
49
+ ## How calls behave
50
+
51
+ - **Every `tests` script of a step feeds one list of checks**: the collection's, the
52
+ step's, and those of an endpoint base, a base collection or a request set it runs
53
+ under (SPEC.md §2.5–§2.7). Strict validation counts them all together.
54
+ - **A check that fails does not stop the script.** The checks after it still run, and
55
+ the step fails.
56
+ - **A mistake in how a check is called is a failed check** that says what is wrong: an
57
+ unknown `specialHandling`, a length that is not a number, a path that is neither text
58
+ nor a list. The checks after it still run.
59
+ - **Any other error stops the script**: a misspelled function name, a call that belongs
60
+ in the other script, or a JavaScript error. The step is marked errored, with the line,
61
+ and checks made before it are kept.
62
+ - **A script is stopped after 10 seconds.**
63
+ - **Check files** in `checks/` call `gta` too, and what they check is reported on the
64
+ step that called them (SPEC.md §5).
65
+
66
+ ---
67
+
68
+ ## Checking the response
69
+
70
+ These run in `tests`. Calling one in `before.script` is an error, since nothing has been
71
+ received yet.
72
+
73
+ ### Paths
74
+
75
+ A path finds a property in the body:
76
+
77
+ | Path | Finds |
78
+ | --------------------------------------- | --------------------------------------------------------------- |
79
+ | `user.name` | A property of a property |
80
+ | `groups.0.name` or `groups[0].name` | A property of an array's first item |
81
+ | `sessions[].id` | The property of every item of an array |
82
+ | `jwt.payload["https://x.io/id"]` | A key holding `.`, `[` or `]`, written in brackets as JSON text |
83
+ | `modules[""].edition` | An empty key |
84
+ | `['jwt', 'payload', 'https://x.io/id']` | A list of keys: each item is one key, whatever it holds |
85
+
86
+ In a list of keys a number is its digits, so `['groups', 0, 'name']` reads an index.
87
+ Every function that takes a path takes a list too, and so does `pathToProperty`.
88
+
89
+ The body is read as checks need it. JSON is used as it is. XML is converted: the root
90
+ element is the one top-level key, an element holding only text becomes that text, and a
91
+ repeated element becomes an array. A text or HTML body is one property, `plaintext`.
92
+ An event stream (`text/event-stream`) is a list with one item per event, holding its
93
+ `data` and, when the event set them, its `event` and `id`: `[1].data.price` is the
94
+ second event's price. SPEC.md §3 has the full rules.
95
+
96
+ ### Values
97
+
98
+ - **A body property compares with its type.** `'12345'` does not equal `12345`, and the
99
+ failure says which is which.
100
+ - **The status and headers compare as text**, so `200` and `'200'` are the same.
101
+ - **A `RegExp` is a pattern**, flags included, tested against the value as text.
102
+
103
+ ### `specialHandling`
104
+
105
+ The last argument of a check may be one of these strings, to change what it asks:
106
+
107
+ | String | Means |
108
+ | -------------------------- | ----------------------------------------------------------------------------------- |
109
+ | _(none, and no value)_ | The property or header is present. |
110
+ | `notThisExpectedKey` | It must not be present. Pass `null` as the value. |
111
+ | `notThisExpectedValue` | It must be present, and not equal the value or match the `RegExp`. |
112
+ | `setAsCollectionVariable` | Save it into the variable the value names, for the steps after. It must be present. |
113
+ | `setAsEnvironmentVariable` | The same. Nothing is written to the environment file. |
114
+ | `dateAsEpoch` | Epoch milliseconds, on the calendar day the value names (below). |
115
+ | `dateWithin<X>Sec` | A date within X seconds of the value, as in `dateWithin5Sec`. |
116
+ | `integerWithin<X>` | A number within X of the value, as in `integerWithin2`. |
117
+ | `isArray` | An array. What it holds is not checked. Pass `null` as the value. |
118
+ | `isArrayAndEmpty` | An empty array. Pass `null` as the value. |
119
+ | `isArrayAndNotEmpty` | An array with at least one item. Pass `null` as the value. |
120
+ | `isArrayAndHasLength` | An array of exactly the value's length. |
121
+
122
+ - The status takes `notThisExpectedValue` and the two `setAs…` strings. A header takes
123
+ those and `notThisExpectedKey`. The rest are for body properties.
124
+ - **`dateAsEpoch`**: the property holds epoch milliseconds, as a number or as digits.
125
+ The value is a number of seconds from now (`0` is today, `86400` tomorrow), or a date
126
+ whose first ten characters, `2026-10-01`, must match. Days are the calendar days of
127
+ the machine running the test.
128
+ - **`dateWithin<X>Sec`**: the property and the value are each an ISO 8601 date or epoch
129
+ milliseconds.
130
+ - **Saving** keeps a string, number, boolean or null as it is. An object or array is
131
+ saved as its JSON text.
132
+
133
+ ### `gta.expectResponseStatusCodeToBe`
134
+
135
+ ```js
136
+ gta.expectResponseStatusCodeToBe(expected, specialHandling?)
137
+ ```
138
+
139
+ The status code is `expected`, or matches it.
140
+
141
+ ```js
142
+ gta.expectResponseStatusCodeToBe(201)
143
+ gta.expectResponseStatusCodeToBe(/^2\d\d$/) // any 2xx
144
+ gta.expectResponseStatusCodeToBe(500, 'notThisExpectedValue') // anything but 500
145
+ gta.expectResponseStatusCodeToBe('lastStatus', 'setAsCollectionVariable')
146
+ ```
147
+
148
+ ### `gta.expectResponseToHaveHeader`
149
+
150
+ ```js
151
+ gta.expectResponseToHaveHeader(name, expected?, specialHandling?)
152
+ ```
153
+
154
+ The header is present, and with `expected`, equals it or matches it.
155
+
156
+ ```js
157
+ gta.expectResponseToHaveHeader('X-Request-Id')
158
+ gta.expectResponseToHaveHeader('Content-Type', /^application\/json/)
159
+ gta.expectResponseToHaveHeader('Cache-Control', 'no-store')
160
+ gta.expectResponseToHaveHeader('X-Debug', null, 'notThisExpectedKey')
161
+ gta.expectResponseToHaveHeader('Server', /nginx/, 'notThisExpectedValue')
162
+ gta.expectResponseToHaveHeader('X-Request-Id', 'requestId', 'setAsCollectionVariable')
163
+ ```
164
+
165
+ - The name matches in any case.
166
+ - A header sent more than once is its values joined with `, `, as in `a=1, b=2`.
167
+
168
+ ### `gta.expectResponseBodyToHaveProperty`
169
+
170
+ ```js
171
+ gta.expectResponseBodyToHaveProperty(path, expected?, specialHandling?)
172
+ ```
173
+
174
+ The property at [`path`](#paths) is present, and with `expected`, equals it or matches
175
+ it.
176
+
177
+ ```js
178
+ gta.expectResponseBodyToHaveProperty('user.id')
179
+ gta.expectResponseBodyToHaveProperty('user.name', 'Ada')
180
+ gta.expectResponseBodyToHaveProperty('user.email', /@example\.com$/)
181
+ gta.expectResponseBodyToHaveProperty('user.nickname', null, 'notThisExpectedKey')
182
+ gta.expectResponseBodyToHaveProperty('user.score', 100, 'integerWithin2')
183
+ gta.expectResponseBodyToHaveProperty('user.roles', 2, 'isArrayAndHasLength')
184
+ gta.expectResponseBodyToHaveProperty('user.token', 'token', 'setAsCollectionVariable')
185
+ gta.expectResponseBodyToHaveProperty('items[].status', 'active') // every item
186
+ ```
187
+
188
+ - **`expected` is a string, number, boolean, `null` or `RegExp`.** An object or array
189
+ never equals one. Check its properties one by one, use
190
+ [`expectResponseBodyToHaveUnorderedArray`](#gtaexpectresponsebodytohaveunorderedarray)
191
+ for an array, or compare it in [`gta.test`](#gtatest) with `assert.deepEqual`.
192
+ - **A property whose value is `null` is present.**
193
+ - **A path that runs into a `null` before its end**, such as `phone.number` when `phone`
194
+ is `null`, reads as `null` for a check that the value is `null`. For any other check,
195
+ the property is not present.
196
+ - **A path with `[]` checks every item**, and passes only when each one does. An empty
197
+ array has no items, so the property is not present. Saving one saves every item's
198
+ value, as a JSON list.
199
+
200
+ ### `gta.expectResponseBodyToHaveUnorderedArray`
201
+
202
+ ```js
203
+ gta.expectResponseBodyToHaveUnorderedArray(path, list)
204
+ ```
205
+
206
+ The array at `path` holds what `list` describes, in any order. `list` takes one of two
207
+ forms.
208
+
209
+ **A list of values.** Each must be in the array, which may hold others too. A `RegExp`
210
+ is a pattern, which some item must match:
211
+
212
+ ```js
213
+ gta.expectResponseBodyToHaveUnorderedArray('roles', ['admin', 'editor'])
214
+ gta.expectResponseBodyToHaveUnorderedArray('roles', [/^admin/, 'editor'])
215
+ gta.expectResponseBodyToHaveUnorderedArray('users', [{ name: 'Ada' }, { name: /^Grace/ }])
216
+ ```
217
+
218
+ An object in the list matches an item holding each of its properties with that value, or
219
+ matching it when the value is a `RegExp`. The item may have others. A pattern is tested
220
+ against the value as text, so it never matches an item that is an object or an array.
221
+
222
+ **A list of `{ pathToProperty, expectedValue, specialHandling? }` entries.** Together
223
+ they describe **one** item, property by property, and some item must match every entry.
224
+ Call the function once for each item:
225
+
226
+ ```js
227
+ gta.expectResponseBodyToHaveUnorderedArray('users', [
228
+ { pathToProperty: 'name', expectedValue: 'Ada' },
229
+ { pathToProperty: 'role', expectedValue: /^admin/ },
230
+ { pathToProperty: 'nickname', expectedValue: null, specialHandling: 'notThisExpectedKey' },
231
+ { pathToProperty: 'id', expectedValue: 'adaId', specialHandling: 'setAsCollectionVariable' }
232
+ ])
233
+ ```
234
+
235
+ - `pathToProperty` is a path inside the item. `specialHandling` is any of the strings
236
+ above, and a save takes its value from the item that matched.
237
+ - A property may be named twice: once to check it, and once to save it.
238
+ - **Each call prefers items an earlier call did not match.** Two calls with the same
239
+ description find two items when there are two, so each saves from, and strict
240
+ validation counts, a different one. A sort starts this over.
241
+ - **A list of one `notThisExpectedValue` entry depends on strict validation.** Without
242
+ it, the entry means no item has that value, so an empty array passes. With it, the
243
+ entry means one item whose value is something else, as any list does. The step's last
244
+ call to `useStrictValidation` decides.
245
+
246
+ ### `gta.expectResponseBodyToHaveUnorderedArrayNotThisItem`
247
+
248
+ ```js
249
+ gta.expectResponseBodyToHaveUnorderedArrayNotThisItem(path, list)
250
+ ```
251
+
252
+ No item of the array at `path` matches what `list` describes.
253
+
254
+ ```js
255
+ gta.expectResponseBodyToHaveUnorderedArrayNotThisItem('roles', ['owner', /^guest/])
256
+ gta.expectResponseBodyToHaveUnorderedArrayNotThisItem('users', [
257
+ { pathToProperty: 'status', compareValue: 'deleted' },
258
+ { pathToProperty: 'email', compareValue: /@test\.invalid$/ }
259
+ ])
260
+ ```
261
+
262
+ - A list of values: none of them may be in the array, and no item may match a `RegExp`
263
+ among them. An object in the list may hold patterns too, as above.
264
+ - A list of `{ pathToProperty, compareValue }` entries describes one item. The check
265
+ fails when some item matches every entry. `compareValue` may be a `RegExp`.
266
+ - **The key is `compareValue`, not `expectedValue`.** An entry without it matches no
267
+ item, so the check always passes.
268
+
269
+ ### `gta.sortResponseBodyArrays`
270
+
271
+ ```js
272
+ gta.sortResponseBodyArrays(property)
273
+ ```
274
+
275
+ Sorts every array of objects that holds `property`, anywhere in the body, for the
276
+ checks after it. Use it when an API returns a list in no fixed order and a check names
277
+ an index.
278
+
279
+ ```js
280
+ gta.sortResponseBodyArrays('id')
281
+ gta.expectResponseBodyToHaveProperty('accounts[0].id', 'acct-100')
282
+ ```
283
+
284
+ - `property` may be a path inside each item, such as `id.value`. Arrays inside the items
285
+ are sorted too.
286
+ - Items without the property go last. Values compare alphanumerically, so `Group 2`
287
+ comes before `Group 10`.
288
+ - Checks made before the call see the order as received, and so does `res.body`.
289
+ - Calling it again sorts by the new property first, and by the earlier ones where that
290
+ ties.
291
+ - Called with no property, it sorts nothing and writes a warning to the step's console.
292
+
293
+ ---
294
+
295
+ ## Strict validation
296
+
297
+ ### `gta.useStrictValidation`
298
+
299
+ ```js
300
+ gta.useStrictValidation(enabled?)
301
+ ```
302
+
303
+ Fails the step unless every property of the body is checked, ignored or saved. It
304
+ catches a response that gained a field no test looks at. `enabled` is `true` when left
305
+ out.
306
+
307
+ ```js
308
+ gta.useStrictValidation()
309
+ gta.expectResponseBodyToHaveProperty('id', 'orderId', 'setAsCollectionVariable')
310
+ gta.expectResponseBodyToHaveProperty('status', 'open')
311
+ gta.ignoreResponseBodyProperty('createdAt')
312
+ ```
313
+
314
+ - It adds one check, `Strict: every body property is asserted`, which lists each
315
+ property left over.
316
+ - It is judged after every `tests` script of the step has run, over what any of them
317
+ checked. Put it in the collection's `tests` to cover every step.
318
+ - `null`, `""`, and empty arrays and objects never need a check of their own.
319
+ - A check of a value's content accounts for it and everything inside it. A check of
320
+ shape only (`isArray`, `isArrayAndHasLength`, or that an object is present) does not
321
+ vouch for what is inside.
322
+ - `false` turns it off. The last call wins, so a step can turn off what the collection
323
+ turned on. `'true'` as text counts as `true`, so a variable can decide:
324
+ `gta.useStrictValidation(gta.get('strictValidation'))`.
325
+ - A binary or HTML body has no properties, so strict validation passes.
326
+
327
+ ### `gta.ignoreResponseBodyProperty`
328
+
329
+ ```js
330
+ gta.ignoreResponseBodyProperty(path)
331
+ ```
332
+
333
+ Counts the property at `path`, and everything inside it, as checked, without checking
334
+ it. For values that change on every call, such as timestamps.
335
+
336
+ ```js
337
+ gta.ignoreResponseBodyProperty('meta')
338
+ gta.ignoreResponseBodyProperty('items[].updatedAt')
339
+ ```
340
+
341
+ It changes nothing unless strict validation is on.
342
+
343
+ ### `gta.ignoreResponseBodyArrayObjectProperty`
344
+
345
+ ```js
346
+ gta.ignoreResponseBodyArrayObjectProperty(arrayPath, propertyPath)
347
+ ```
348
+
349
+ The same, for one property of every item of an array.
350
+ `gta.ignoreResponseBodyArrayObjectProperty('items', 'updatedAt')` is
351
+ `gta.ignoreResponseBodyProperty('items[].updatedAt')`.
352
+
353
+ ---
354
+
355
+ ## Checks of your own
356
+
357
+ ### `gta.test`
358
+
359
+ ```js
360
+ gta.test(name, fn)
361
+ ```
362
+
363
+ A named check, for anything the functions above do not cover. It passes unless `fn`
364
+ throws, or the promise it returns rejects, and then the error's message is the reason.
365
+
366
+ ```js
367
+ gta.test('ids are unique', () => {
368
+ const ids = res.body.items.map((item) => item.id)
369
+ assert.equal(new Set(ids).size, ids.length)
370
+ })
371
+
372
+ gta.test('total is the sum of the lines', () => {
373
+ const sum = res.body.lines.reduce((total, line) => total + line.amount, 0)
374
+ assert.equal(res.body.total, sum)
375
+ })
376
+ ```
377
+
378
+ - `assert` is Node's strict `assert`, also reachable as `gta.assert`.
379
+ - `fn` may be `async`. The step waits for it, whether or not the script does.
380
+ - An endpoint base's named checks are never replaced by a step's own (SPEC.md §2.6).
381
+
382
+ ---
383
+
384
+ ## Variables
385
+
386
+ ### `gta.get`
387
+
388
+ ```js
389
+ gta.get(name)
390
+ ```
391
+
392
+ A variable's current value, from whichever layer sets it: the project, the collection,
393
+ the environment, a data file row, or a value saved or set earlier in the run.
394
+ `undefined` when no layer does.
395
+
396
+ ```js
397
+ gta.expectResponseStatusCodeToBe(gta.get('expectedStatus'))
398
+ ```
399
+
400
+ A value comes back with its type. Every value from a CSV data file is text.
401
+
402
+ ### `gta.set`
403
+
404
+ ```js
405
+ gta.set(name, value, options?)
406
+ ```
407
+
408
+ Sets a variable, which `{{name}}` and `gta.get(name)` read from then on: in this step's
409
+ request when it is set in `before.script`, and in every step after.
410
+
411
+ ```js
412
+ gta.set('traceId', gta.uuidv7())
413
+ gta.set(
414
+ 'ids',
415
+ res.body.items.map((item) => item.id)
416
+ ) // saved as '["a","b"]'
417
+ gta.set('adminId', res.body.id, { scope: 'run' })
418
+ ```
419
+
420
+ - **Anything computed goes here**, since `vars` in a file hold plain values only
421
+ (SPEC.md §4). A collection's `before.script` runs before every step, so a value set
422
+ there is fresh for each.
423
+ - A string, number, boolean or `null` is kept as it is. An object or array is saved as
424
+ its JSON text, so `{{ids}}` writes the list into a JSON body, and `forEach: '{{ids}}'`
425
+ sends a request for each item. Read it back in code with `JSON.parse(gta.get('ids'))`.
426
+ `undefined` is saved as `null`.
427
+ - **In a collection with a data file**, a value lasts the rest of its row.
428
+ `{ scope: 'run' }` keeps it for every row after, and for teardown (SPEC.md §2.10).
429
+ Any other `scope` is an error.
430
+ - Nothing is written to a file.
431
+ - SPEC.md §4 gives the order in which layers win.
432
+
433
+ ---
434
+
435
+ ## Skipping steps
436
+
437
+ ### `gta.skip`
438
+
439
+ ```js
440
+ gta.skip(reason?)
441
+ ```
442
+
443
+ In `before.script` only. The request is not sent, and the step is reported as skipped,
444
+ with the reason. A skipped step never fails a run.
445
+
446
+ ```js
447
+ if (!gta.get('adminToken')) gta.skip('no admin account in this environment')
448
+ ```
449
+
450
+ - The script runs to its end. No later `before.script` runs for the step: when the
451
+ collection's skips it, the step's own does not run.
452
+ - In `tests` it is an error, because the request has been sent. Use `gta.skipRest`
453
+ there.
454
+ - To skip a step depending on a feature flag, give it `flags:` (SPEC.md §2.9).
455
+
456
+ ### `gta.skipRest`
457
+
458
+ ```js
459
+ gta.skipRest(reason?)
460
+ ```
461
+
462
+ Skips the steps after this one, each reported as skipped with the reason.
463
+
464
+ ```js
465
+ if (res.status === 404) gta.skipRest('no such account, so nothing more to check')
466
+ ```
467
+
468
+ - In `tests`, this step's own result stands. In `before.script`, this step is skipped
469
+ too.
470
+ - It skips only the current row. The next row of a data file, and teardown, still run.
471
+ - The first reason given stands.
472
+
473
+ ---
474
+
475
+ ## Feature flags
476
+
477
+ ### `gta.flag`
478
+
479
+ ```js
480
+ gta.flag(name)
481
+ ```
482
+
483
+ A feature flag's value in this run: a string, number or boolean, from the environment,
484
+ the flag command or an override (SPEC.md §2.9). Use it to check something different
485
+ when a flag is on, rather than skip a step.
486
+
487
+ ```js
488
+ if (gta.flag('newCheckout')) {
489
+ gta.expectResponseBodyToHaveProperty('total.currency', 'USD')
490
+ }
491
+ ```
492
+
493
+ A flag the run does not know is an error, so a misspelled name stops the script rather
494
+ than quietly reading as off.
495
+
496
+ ---
497
+
498
+ ## Generated values
499
+
500
+ ### `gta.uuid`
501
+
502
+ ```js
503
+ gta.uuid()
504
+ ```
505
+
506
+ A random (version 4) UUID, such as `f397d495-8679-42de-8b69-d6ef86b3f5a1`.
507
+
508
+ ### `gta.uuidv7`
509
+
510
+ ```js
511
+ gta.uuidv7()
512
+ ```
513
+
514
+ A time-ordered (version 7) UUID, such as `01a0f78d-cecb-73c4-ac6e-557141551574`. Ids made
515
+ later sort later, which suits a request id or a record that must read in creation
516
+ order.
517
+
518
+ ### `gta.randomInt`
519
+
520
+ ```js
521
+ gta.randomInt(min, max)
522
+ ```
523
+
524
+ A whole number from `min` to `max`, both included: `gta.randomInt(1, 6)` rolls a die.
525
+
526
+ ### `gta.date`
527
+
528
+ ```js
529
+ gta.date(format, secondsOffset?, timeZone?)
530
+ ```
531
+
532
+ The time now, moved by `secondsOffset` seconds and formatted. `secondsOffset` is `0`
533
+ when left out, and `timeZone` is `'local'`.
534
+
535
+ ```js
536
+ gta.date('%Y-%m-%d') // today: 2026-10-01
537
+ gta.date('%F', 86400, 'utc') // tomorrow, in UTC
538
+ gta.date('%FT%T%z', -3600, 'America/New_York') // an hour ago: 2026-10-01T04:15:00-0400
539
+ ```
540
+
541
+ | Specifier | Gives | Specifier | Gives |
542
+ | --------- | ---------------------------- | --------- | ---------------------------- |
543
+ | `%Y` | Year: `2026` | `%p` | `AM` or `PM` |
544
+ | `%y` | Year, two digits: `26` | `%b` | Month, short: `Oct` |
545
+ | `%m` | Month: `01`–`12` | `%B` | Month: `October` |
546
+ | `%d` | Day: `01`–`31` | `%a` | Weekday, short: `Thu` |
547
+ | `%e` | Day, space-padded: ` 1`–`31` | `%A` | Weekday: `Thursday` |
548
+ | `%H` | Hour: `00`–`23` | `%j` | Day of the year: `001`–`366` |
549
+ | `%I` | Hour: `01`–`12` | `%Z` | Time zone: `PDT` |
550
+ | `%M` | Minute: `00`–`59` | `%z` | Offset from UTC: `-0700` |
551
+ | `%S` | Second: `00`–`59` | `%s` | Epoch seconds |
552
+ | `%L` | Millisecond: `000`–`999` | `%F` | `%Y-%m-%d` |
553
+ | `%%` | `%` | `%T` | `%H:%M:%S` |
554
+
555
+ - A specifier not listed is left as written, so `%Q` stays `%Q` and a typo shows.
556
+ - A negative `secondsOffset` is in the past.
557
+ - `timeZone` is `local`, the time zone of the machine running the test; `utc`; an IANA
558
+ name, such as `America/New_York`; or a military letter. `A` to `M` are 1 to 12 hours
559
+ ahead of UTC, skipping `J`, `N` to `Y` are 1 to 12 hours behind, and `Z` is UTC, so
560
+ `U` is -08:00, not UTC. `IST` is India.