@schwabyio/gta 0.12.0 → 0.14.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
@@ -23,7 +23,7 @@ The package has no dependencies to install: everything `gta` uses is bundled int
23
23
 
24
24
  ## A first project
25
25
 
26
- A project is a folder holding a `collections/` directory, an `environments/` one and a
26
+ A project is a folder holding a `collections/` folder, an `environments/` one and a
27
27
  `settings.yml`. The smallest project `gta` runs is three files:
28
28
 
29
29
  ```yaml
@@ -139,6 +139,43 @@ In a monorepo, projects that share a global project (`uses:` in `project.yml`) s
139
139
  setting by setting it again in its own file. Each project still needs a `settings.yml`,
140
140
  even an empty one.
141
141
 
142
+ ## Project rules
143
+
144
+ A `rules.yml` beside `project.yml` writes down how a project's files are named, laid out
145
+ and written, so everyone working on it, people and coding agents alike, keeps it the
146
+ same:
147
+
148
+ ```yaml
149
+ # rules.yml
150
+ ids:
151
+ collections: kebab-case # or a pattern, such as '{folder}-[a-z0-9-]+'
152
+ layout:
153
+ folders: required # every collection in a folder of collections/
154
+ docs:
155
+ collections: required
156
+ tags:
157
+ allowed: [smoke, regression]
158
+ steps:
159
+ names: required
160
+ tests:
161
+ only: [gta] # tests call the gta.* functions, and nothing else
162
+ statusCode: required
163
+ guide: |
164
+ Name each step for what it proves.
165
+ ```
166
+
167
+ ```sh
168
+ gta rules # the rules in effect, where each came from, what each means, the guide
169
+ gta lint # check every file against them
170
+ gta lint --json # the findings as JSON, for tools and agents
171
+ ```
172
+
173
+ `gta lint` prints each finding at its file and line, with the rule it breaks, and exits
174
+ `1` when it finds one. Rules never change a run: a file that breaks one still runs. A
175
+ global project's `rules.yml` is shared like its `settings.yml`, and a project changes or
176
+ turns off (`null`) any rule in its own file. Every rule is in
177
+ [SPEC.md §1.4](https://github.com/schwabyio/gravity/blob/main/SPEC.md#14-rulesyml).
178
+
142
179
  ## In CI
143
180
 
144
181
  ```yaml
@@ -147,11 +184,113 @@ even an empty one.
147
184
  with:
148
185
  node-version: 22
149
186
  - run: npm install -g @schwabyio/gta
187
+ - run: gta lint
150
188
  - run: gta all --environmentType staging --generateJUnitResults
151
189
  env:
152
190
  apiKey: ${{ secrets.STAGING_API_KEY }}
153
191
  ```
154
192
 
193
+ ## From Playwright and other code
194
+
195
+ The package is also a library. A test written in code can run a collection or a request
196
+ set, then use the values it saved, such as a token or the id of a user it created, in a
197
+ browser test.
198
+
199
+ ### Playwright
200
+
201
+ `@schwabyio/gta/playwright` gives you Playwright's `test` with a `gta` fixture. Point it
202
+ at the project in `playwright.config.ts`:
203
+
204
+ ```ts
205
+ // playwright.config.ts
206
+ import { defineConfig } from '@playwright/test'
207
+ import type { GravityConfig } from '@schwabyio/gta/playwright'
208
+
209
+ export default defineConfig<{}, GravityConfig>({
210
+ use: {
211
+ gravity: { project: '../api-tests', environment: 'staging' }
212
+ }
213
+ })
214
+ ```
215
+
216
+ ```ts
217
+ // tests/dashboard.spec.ts
218
+ import { test, expect } from '@schwabyio/gta/playwright'
219
+
220
+ test('a new user sees their dashboard', async ({ page, gta }) => {
221
+ // requests/create-user.yml, run as a use: step would run it
222
+ const user = await gta.use('create-user', { plan: 'pro' })
223
+
224
+ await page.goto(`/users/${user.values.userId}`)
225
+ await expect(page.getByRole('heading')).toHaveText('Welcome')
226
+
227
+ // collections/billing.yml, starting from what create-user saved
228
+ await gta.run('billing', { vars: user.values })
229
+ })
230
+ ```
231
+
232
+ - Each `gta.run` and `gta.use` call is a step in Playwright's report. Each request is a
233
+ step inside it, linked to its step in the YAML, with the request and response attached.
234
+ - A run that fails fails the test at the line that called it, with what failed. With
235
+ `soft: true` the test goes on and fails at the end, as `expect.soft` does.
236
+ - `project` is relative to the folder `playwright.config.ts` is in, and defaults to it.
237
+ `environment`, `flags`, `bail` and `timeoutCollection` go beside it. The project opens
238
+ once per worker, so an environment's flag command runs once per worker.
239
+ - A run counts toward the test's timeout, and one still going when the test ends is
240
+ stopped.
241
+ - To use this `test` with fixtures of your own, combine them with Playwright's
242
+ `mergeTests`.
243
+
244
+ It needs `@playwright/test` 1.51 or later, which installing `gta` does not install.
245
+
246
+ ### Any other code
247
+
248
+ ```js
249
+ import { openProject } from '@schwabyio/gta'
250
+
251
+ const project = await openProject('api-tests', { environment: 'staging' })
252
+ const login = await project.use('login', { username: 'alice' })
253
+ const checkout = await project.run('checkout', { vars: login.values })
254
+ if (!checkout.passed) throw new Error(checkout.failures)
255
+ ```
256
+
257
+ **`openProject(folder, options)`** opens the project in `folder`, the one holding
258
+ `collections/`. The options are `environment`, `flags`, `bail` and `timeoutCollection`.
259
+ Each one you leave out comes from `settings.yml`, the same way `gta` reads it, but here
260
+ the project does not need a `settings.yml`.
261
+
262
+ **`project.run(collection, options)`** runs a collection the way `gta` runs it: setup,
263
+ then the steps once for each data row, then teardown. Name the collection by its id or
264
+ its place in `collections/` (`checkout/sessions`). `tags` and `notTags` don't apply,
265
+ since you name what runs, and a collection with `exclude: true` runs too. The options:
266
+
267
+ | Option | What it does |
268
+ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------ |
269
+ | `steps` | Run only these steps, named as reports name them or numbered from 1. They run in the file's order, and setup and teardown still run. |
270
+ | `vars` | Values the run starts with. They sit over the environment and under a data row. |
271
+ | `bail` | Stop at the first failing step. |
272
+ | `signal` | An `AbortSignal` that stops the run. |
273
+ | `onResult` | `(result, step) => void`, called as each request finishes. |
274
+
275
+ **`project.use(set, params, options)`** runs a request set as a `use:` step would:
276
+ `login` is `requests/login.yml`, in the project or its global project. `params` are what
277
+ `with:` gives, and a param you leave out takes its default. The options are those of
278
+ `run`, without `steps`.
279
+
280
+ Both resolve to the same outcome, however the steps fare:
281
+
282
+ | Field | What it holds |
283
+ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
284
+ | `passed` | `true` when nothing failed or errored and the run finished. |
285
+ | `values` | Every value the run set or captured, by name: `gta.set`, and checks that save what they read, such as `'setAsCollectionVariable'`. Secrets are not hidden here. |
286
+ | `summary` | Totals, and every request's result as gta's JSON report holds it, with secrets shown as `[secret: NAME]`. |
287
+ | `steps` | Where each result's step is: its file and line. |
288
+ | `failures` | What went wrong, as `gta` prints it under Failures. Empty when the run passed. |
289
+ | `error` | Why the run did not start or finish: a file that will not load, `timeoutCollection`, or a cancel. Otherwise `null`. |
290
+
291
+ They reject only when a collection, step or request set doesn't exist, or a value isn't a
292
+ string, number, boolean or null. Types ship with the package.
293
+
155
294
  ## The file format
156
295
 
157
296
  [SPEC.md](https://github.com/schwabyio/gravity/blob/main/SPEC.md) specifies every file,
@@ -159,6 +298,10 @@ every key, and every rule that makes a file invalid. It is written for people an
159
298
  agents alike, and ends with a complete project to start from. It also ships in this
160
299
  package as `dist/SPEC.md`, and `gta`'s messages cite its sections, as in "(SPEC.md §2.5)".
161
300
 
301
+ [FUNCTIONS.md](https://github.com/schwabyio/gravity/blob/main/FUNCTIONS.md) documents every
302
+ `gta` function that `tests` and `before.script` can call, with examples. It ships as
303
+ `dist/FUNCTIONS.md`.
304
+
162
305
  ## License
163
306
 
164
307
  MIT. The packages bundled into `gta` keep their own licenses, collected in