@gfdelarue/testkit 0.6.0 → 0.6.2
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 +455 -56
- package/bin/testkit-windows-owner-arm64.exe +0 -0
- package/bin/testkit-windows-owner-x64.exe +0 -0
- package/dist/app/bugs/batch.js +1 -0
- package/dist/app/bugs/ci-report.js +2 -2
- package/dist/app/bugs/ci-summary.js +3 -3
- package/dist/app/bugs/draft.js +2 -2
- package/dist/app/bugs/file.js +1 -1
- package/dist/app/bugs/guide.js +1 -1
- package/dist/app/bugs/record.js +1 -1
- package/dist/app/bugs/run-reading.js +1 -1
- package/dist/app/bugs/store.js +1 -1
- package/dist/app/campaigns/summary.js +1 -1
- package/dist/app/cleanup/index.js +1 -1
- package/dist/app/db-schema/prepare.js +1 -1
- package/dist/app/db-schema/refresh.js +1 -1
- package/dist/app/db-schema/verify.js +1 -1
- package/dist/app/destroy/index.js +1 -1
- package/dist/app/environments/config-driven.js +1 -1
- package/dist/app/environments/file-setup.js +1 -1
- package/dist/app/environments/routing.js +1 -1
- package/dist/app/environments/static-values.js +1 -1
- package/dist/app/environments/supplied.js +1 -1
- package/dist/app/lint/shared.js +1 -1
- package/dist/app/run/live-run.js +1 -1
- package/dist/app/run/orchestrator.js +1 -1
- package/dist/app/run/planning.js +1 -1
- package/dist/app/run/results.js +1 -1
- package/dist/app/run/run-finalization.js +1 -1
- package/dist/app/run/run-finisher.js +1 -0
- package/dist/app/run/setup/runtime-node-setup-protocol.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-worker.js +1 -1
- package/dist/app/run/setup/runtime-node-setup.js +2 -2
- package/dist/app/status/runs.js +1 -1
- package/dist/app/stop/index.js +1 -1
- package/dist/app/tracker/index.js +1 -1
- package/dist/app/tracker/token.js +2 -2
- package/dist/app/typecheck/index.js +4 -4
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-flags.js +1 -1
- package/dist/cli/commands/bug/file.js +3 -2
- package/dist/cli/framework/help.js +5 -5
- package/dist/cli/framework/parser.js +1 -1
- package/dist/cli/json-errors.js +1 -1
- package/dist/cli/renderers/bug/text.js +1 -1
- package/dist/cli/renderers/run/formatting.js +1 -1
- package/dist/config/loader/config-loader.js +1 -1
- package/dist/config/loader/discover-tests.js +1 -1
- package/dist/config/loader/discovery-result.js +1 -0
- package/dist/config/loader/index.js +1 -1
- package/dist/config/loader/runtime-isolation.js +1 -1
- package/dist/config/loader/skip-config.js +1 -1
- package/dist/config/loader/test-selection.js +1 -1
- package/dist/database/admin.js +5 -2
- package/dist/database/call-caps.js +1 -0
- package/dist/database/cleanup.js +1 -1
- package/dist/database/configured-steps.js +1 -1
- package/dist/database/constants.js +1 -1
- package/dist/database/docker-endpoint.js +1 -0
- package/dist/database/docker-metadata.js +2 -2
- package/dist/database/docker.js +5 -5
- package/dist/database/index.js +2 -1
- package/dist/database/lifecycle-cleanup.js +1 -1
- package/dist/database/local-postgres.js +4 -1
- package/dist/database/naming.js +1 -1
- package/dist/database/operation-deadline.js +1 -0
- package/dist/database/postgres/connection-check.js +1 -1
- package/dist/database/postgres/index.js +2 -2
- package/dist/database/postgres/owned-exec.js +27 -0
- package/dist/database/postgres/protocol.js +2 -2
- package/dist/database/provider.js +1 -0
- package/dist/database/roles.js +2 -2
- package/dist/database/schema-operations.js +5 -1
- package/dist/database/schema-source.js +3 -3
- package/dist/database/steps.js +1 -1
- package/dist/database/template-steps.js +4 -4
- package/dist/domain/suite-selection.js +1 -1
- package/dist/engines/adapters/evidence-files.js +1 -1
- package/dist/engines/adapters/execution.js +1 -1
- package/dist/engines/node-vitest/adapter/adapter.js +1 -1
- package/dist/engines/node-vitest/adapter/driver.js +2 -2
- package/dist/engines/node-vitest/runtime/runtime-input.js +1 -1
- package/dist/engines/playwright/adapter/adapter.js +1 -1
- package/dist/engines/playwright/adapter/browser-network-evidence.js +4 -0
- package/dist/engines/playwright/adapter/config.js +16 -6
- package/dist/engines/playwright/adapter/evidence.js +2 -1
- package/dist/engines/playwright/adapter/failure-details.js +2 -2
- package/dist/engines/playwright/adapter/reporter.js +1 -1
- package/dist/engines/playwright/runtime/browser-network.js +1 -0
- package/dist/engines/playwright/runtime/browser-traffic.js +1 -0
- package/dist/engines/playwright/runtime/chromium-environment.js +1 -0
- package/dist/engines/playwright/runtime/emulation.js +1 -0
- package/dist/engines/playwright/runtime/index.js +1 -1
- package/dist/engines/playwright/runtime/managed-test.js +1 -1
- package/dist/engines/playwright/runtime/runtime-input.js +2 -2
- package/dist/environment/lifecycle-controller.js +1 -1
- package/dist/environment/lifecycle.js +1 -1
- package/dist/environment/maintenance.js +1 -1
- package/dist/environment/run-environment.js +1 -1
- package/dist/environment/run-stopping.js +1 -1
- package/dist/environment/runtime-manager.js +1 -1
- package/dist/evidence/artifacts.js +5 -2
- package/dist/evidence/bundles.js +2 -1
- package/dist/evidence/compressed-artifacts.js +1 -0
- package/dist/evidence/environment-record.js +1 -1
- package/dist/evidence/index.js +1 -1
- package/dist/evidence/live-run-summary.js +1 -0
- package/dist/evidence/local-paths.js +1 -0
- package/dist/evidence/maintenance.js +1 -1
- package/dist/evidence/operation-timings.js +1 -1
- package/dist/evidence/redaction.js +4 -4
- package/dist/evidence/run-evidence.js +1 -0
- package/dist/evidence/setup-progress.js +1 -1
- package/dist/evidence/storage-inventory.js +1 -1
- package/dist/evidence/storage.js +2 -2
- package/dist/kernel/redaction-targets.js +1 -1
- package/dist/kernel/redaction.js +7 -4
- package/dist/process/engine-environment-keys.js +1 -0
- package/dist/process/environment-overlay.js +1 -1
- package/dist/process/environment.js +1 -1
- package/dist/process/execa-bundle.json +3 -3
- package/dist/process/files/evidence-writes.js +1 -0
- package/dist/process/files/product-dir.js +1 -1
- package/dist/process/host-process.js +1 -1
- package/dist/process/index.js +1 -1
- package/dist/process/lifecycle-fence.js +1 -1
- package/dist/process/lock-progress.js +2 -0
- package/dist/process/locks.js +4 -4
- package/dist/process/process-identity.js +1 -1
- package/dist/process/process.js +35 -35
- package/dist/process/recovery.js +1 -1
- package/dist/process/runs/manifest.js +1 -1
- package/dist/process/runs/ownership.js +1 -1
- package/dist/process/runs/stop.js +1 -1
- package/dist/process/shutdown.js +1 -1
- package/dist/process/windows-native.js +1 -1
- package/dist/repo/history.js +7 -4
- package/dist/repo/managed-git.js +1 -1
- package/dist/repo/state.js +4 -4
- package/dist/steps/environment.js +1 -1
- package/dist/toolchains/node-provisioning.js +2 -2
- package/dist/tracker/gitea.js +1 -1
- package/dist/tracker/github.js +1 -1
- package/dist/tracker/http.js +1 -1
- package/dist/tracker/ownership.js +1 -0
- package/dist/tracker/redaction.js +1 -1
- package/dist/tracker/responses.js +1 -1
- package/dist/types/playwright.d.ts +38 -2
- package/dist/types/workspace.d.ts +4 -4
- package/docs/bug-records.md +16 -10
- package/docs/engines.md +52 -4
- package/docs/release-notes.md +749 -0
- package/package.json +14 -2
- package/testkit-config-schema.md +36 -42
- package/dist/config/loader/task-policy.js +0 -1
- package/dist/environment/lifecycle-artifacts.js +0 -1
package/docs/release-notes.md
CHANGED
|
@@ -1,3 +1,752 @@
|
|
|
1
|
+
# 0.6.2
|
|
2
|
+
|
|
3
|
+
## Static imports from `@gfdelarue/testkit/playwright` work in a CommonJS product
|
|
4
|
+
|
|
5
|
+
In a product whose `package.json` doesn't set `"type": "module"`, a `ui` test
|
|
6
|
+
that imported a Testkit helper from `@gfdelarue/testkit/playwright` got
|
|
7
|
+
`undefined`, and threw a `TypeError` when it called it
|
|
8
|
+
([gfdelarue/testkit#505](https://github.com/gfdelarue/testkit/issues/505)).
|
|
9
|
+
Every helper was affected, from `browserRequests` and `emulateNetwork` to
|
|
10
|
+
`waitForUiSettled`. `test`, `expect`, and Playwright's other exports still
|
|
11
|
+
worked. Static imports now get every helper, as they do in an ES module product.
|
|
12
|
+
|
|
13
|
+
Playwright compiles such a test to CommonJS, so each static import becomes a
|
|
14
|
+
`require()`. The entry re-exported Playwright with `export *`, which also passed
|
|
15
|
+
on the `"module.exports"` export of Testkit's managed `@playwright/test`. Node's
|
|
16
|
+
`require()` returns that export in place of the module, so it returned the
|
|
17
|
+
managed `test`. The entry now names each of Playwright's runtime exports.
|
|
18
|
+
`require("@playwright/test")` in a test still returns the managed `test`.
|
|
19
|
+
|
|
20
|
+
# 0.6.1
|
|
21
|
+
|
|
22
|
+
## Each `ui` test's browser traffic is in the run evidence
|
|
23
|
+
|
|
24
|
+
Testkit now records the requests every `ui` test's pages send
|
|
25
|
+
([gfdelarue/testkit#496](https://github.com/gfdelarue/testkit/issues/496)).
|
|
26
|
+
For each `ui` file whose tests sent requests, the run evidence has
|
|
27
|
+
`browser-network.json` and `browser-network-report.md`, from each test's final
|
|
28
|
+
attempt. Rows group page loads and API calls by service, method, and path, with
|
|
29
|
+
IDs replaced by `:id`. Other requests count toward totals by type, and other
|
|
30
|
+
origins appear by host only. The record holds no query strings, headers, or
|
|
31
|
+
bodies.
|
|
32
|
+
|
|
33
|
+
The report lists leads: a write sent more than once with the same body, and a
|
|
34
|
+
page load or API call that failed in a test that passed. Leads never fail a
|
|
35
|
+
test. Recording is always on. On a page that sent 400 requests it added no time
|
|
36
|
+
we could measure.
|
|
37
|
+
|
|
38
|
+
`browserRequests()` from `@gfdelarue/testkit/playwright` returns the test's
|
|
39
|
+
requests so a test can assert on them:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const payments = (await browserRequests()).filter(
|
|
43
|
+
(request) => request.service === "api" && request.method === "POST" && request.path === "/payments",
|
|
44
|
+
);
|
|
45
|
+
expect(payments).toHaveLength(1);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
[Check a ui test's browser traffic](../README.md#check-a-ui-tests-browser-traffic)
|
|
49
|
+
describes the record, its limits, and the entry fields.
|
|
50
|
+
|
|
51
|
+
## A `ui` test can slow its browser's network and CPU
|
|
52
|
+
|
|
53
|
+
`@gfdelarue/testkit/playwright` exports `emulateNetwork(page, conditions)` and
|
|
54
|
+
`emulateCpu(page, slowdown)`
|
|
55
|
+
([gfdelarue/testkit#495](https://github.com/gfdelarue/testkit/issues/495)).
|
|
56
|
+
They set Chromium's own throttling through the DevTools protocol, so a test can
|
|
57
|
+
fail when a change makes a page unusable on a slow connection or a slow device:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
test("the dashboard is usable on a slow connection", async ({ page }) => {
|
|
61
|
+
await emulateNetwork(page, "slow-4g");
|
|
62
|
+
await page.goto("/dashboard");
|
|
63
|
+
await expect(page.getByRole("heading", { name: "Orders" })).toBeVisible({ timeout: 10_000 });
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`emulateNetwork` takes `"fast-4g"`, `"slow-4g"`, or `"3g"`, with the values of
|
|
68
|
+
DevTools' presets of the same name, or custom
|
|
69
|
+
`{ latencyMs, downloadKbps, uploadKbps }`. It converts kilobits per second to
|
|
70
|
+
the protocol's bytes per second. `emulateCpu` takes a fixed multiplier from 1
|
|
71
|
+
to 100, which slows the page relative to the machine that runs it. The network
|
|
72
|
+
conditions apply to the page you pass in, and the CPU slowdown to the browser
|
|
73
|
+
process that runs it.
|
|
74
|
+
[Slow the browser's network and CPU](../README.md#slow-the-browsers-network-and-cpu)
|
|
75
|
+
lists the profile values, what each setting reaches, and how to set time limits
|
|
76
|
+
that don't fail on a slow CI runner.
|
|
77
|
+
|
|
78
|
+
Testkit's own Postgres client calls ran with the 30-minute timeout meant for
|
|
79
|
+
long user SQL, and the source schema's replay into a template with the
|
|
80
|
+
60-minute step timeout. A schema-only `pg_dump` that couldn't finish used up
|
|
81
|
+
all of `db schema refresh`'s or `verify`'s time limit, and the error said only
|
|
82
|
+
that a Postgres client was cancelled
|
|
83
|
+
([gfdelarue/testkit#468](https://github.com/gfdelarue/testkit/issues/468)).
|
|
84
|
+
|
|
85
|
+
Each call now has a cap:
|
|
86
|
+
|
|
87
|
+
- the server version probe before a source schema dump: 60 seconds;
|
|
88
|
+
- a schema-only `pg_dump`: 5 minutes;
|
|
89
|
+
- the source schema's replay into a template: 10 minutes.
|
|
90
|
+
|
|
91
|
+
When the probe or a dump reaches its cap, the error names the call and its
|
|
92
|
+
cap, such as `Dockerized Postgres client for the schema-only pg_dump (300 s
|
|
93
|
+
cap) exceeded its managed deadline`.
|
|
94
|
+
|
|
95
|
+
In `db schema verify` and `refresh`, a `--timeout-seconds` above 600 lengthens
|
|
96
|
+
these caps in proportion, along with the admin statements' `lock_timeout` and
|
|
97
|
+
`statement_timeout` and the role setup's 60-second timeout: a limit of 1200
|
|
98
|
+
seconds doubles them. Elsewhere, including `testkit run`, the caps keep their
|
|
99
|
+
defaults. Configured template steps keep their 60-minute timeout.
|
|
100
|
+
|
|
101
|
+
## A schema operation that stops waiting for a lock says who holds it
|
|
102
|
+
|
|
103
|
+
When `db schema verify` or `refresh` ran out of its time limit while another
|
|
104
|
+
operation on the same product held a lock it needed, the error said only which
|
|
105
|
+
service it was preparing
|
|
106
|
+
([gfdelarue/testkit#468](https://github.com/gfdelarue/testkit/issues/468)). It
|
|
107
|
+
now names the lock, how long it waited, the holder's process and host, and the
|
|
108
|
+
step the holder is on and for how long. A holder from an older Testkit, or one
|
|
109
|
+
that recorded no step, is reported with its progress unknown.
|
|
110
|
+
|
|
111
|
+
A lock whose release failed in Testkit's own process used to block that
|
|
112
|
+
process's later waits until it exited. Testkit now reports it at once.
|
|
113
|
+
|
|
114
|
+
A configured template step's toolchain installation now counts against the
|
|
115
|
+
operation's limit. Only the step's own run doesn't.
|
|
116
|
+
|
|
117
|
+
## `db schema verify` and `refresh` have a time limit
|
|
118
|
+
|
|
119
|
+
`db schema verify` and `db schema refresh` had no overall bound. A Testkit
|
|
120
|
+
statement blocked on another session's lock waited until its own
|
|
121
|
+
`lock_timeout`, and any wait without a limit of its own could hang the
|
|
122
|
+
command. Their cleanup ran with no bound and dropped its errors
|
|
123
|
+
([gfdelarue/testkit#468](https://github.com/gfdelarue/testkit/issues/468)).
|
|
124
|
+
|
|
125
|
+
Each operation now has a time limit, 600 seconds unless `--timeout-seconds`
|
|
126
|
+
sets it. Your configured template steps don't spend it: they keep their own
|
|
127
|
+
step timeout. When the limit runs out, the error lists the setup steps with
|
|
128
|
+
their times, the service being prepared and the wait it stopped in.
|
|
129
|
+
|
|
130
|
+
Cleanup gets its own 3-minute allowance. If it can't finish, the error says
|
|
131
|
+
what it left, and the command fails even when the operation's work
|
|
132
|
+
succeeded. `testkit destroy` removes what's left.
|
|
133
|
+
|
|
134
|
+
A process Testkit stops is awaited for at most 15 seconds after its
|
|
135
|
+
termination begins, or 15 seconds after a local service's shutdown grace.
|
|
136
|
+
After that, Testkit reports it as unsettled instead of waiting.
|
|
137
|
+
|
|
138
|
+
## A retained local database that won't start is rebuilt once
|
|
139
|
+
|
|
140
|
+
Testkit keeps each product's local Postgres cluster in a Docker volume between
|
|
141
|
+
runs. If that cluster was damaged, for example by a host crash while its files
|
|
142
|
+
were half written, its server exited while starting, and every later run failed
|
|
143
|
+
the same way until `testkit destroy`.
|
|
144
|
+
|
|
145
|
+
Testkit now notices when the server exits while it waits for the database to
|
|
146
|
+
become ready. If the cluster was on a volume an earlier run left, and the volume
|
|
147
|
+
carries this product's Testkit labels, Testkit removes the container and the
|
|
148
|
+
volume, says so, and provisions again on a fresh volume:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
[testkit] Testkit is replacing database volume <volume>, because Local database container <container> exited while starting with exit code 1: <the server's last FATAL line, redacted>. The new volume starts with an empty cluster, so its template is rebuilt.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
It does this at most once per provisioning. A server that exits on a volume
|
|
155
|
+
created in the same provisioning fails it, with its exit code and its last FATAL
|
|
156
|
+
or PANIC line. A server that is slow to start, or that refuses connections while
|
|
157
|
+
it starts, is left alone, and readiness still times out after 60 seconds.
|
|
158
|
+
|
|
159
|
+
Testkit also creates new clusters with `initdb --no-sync`, through
|
|
160
|
+
`POSTGRES_INITDB_ARGS`. On Docker Desktop that saves about a second of a cold
|
|
161
|
+
start. A cluster that a host crash catches right after `initdb` is now one of
|
|
162
|
+
the clusters the rebuild replaces.
|
|
163
|
+
|
|
164
|
+
## Admin statements on local Postgres time out
|
|
165
|
+
|
|
166
|
+
A statement Testkit runs on its local Postgres container, such as
|
|
167
|
+
`CREATE DATABASE` or `DROP DATABASE`, waited indefinitely when another session
|
|
168
|
+
held a lock it needed. A `psql` client that didn't return after its statement
|
|
169
|
+
kept the command waiting too. Neither printed anything
|
|
170
|
+
([gfdelarue/testkit#468](https://github.com/gfdelarue/testkit/issues/468)).
|
|
171
|
+
|
|
172
|
+
Each admin statement now runs with a 60-second `lock_timeout` and a 10-minute
|
|
173
|
+
`statement_timeout`. Testkit stops its `docker exec` 30 seconds after the
|
|
174
|
+
statement timeout, then ends the client and its session inside the container,
|
|
175
|
+
as it already did after a cancellation. The error names the statement and its
|
|
176
|
+
limits. When the statement ran long enough to be checked, the error also says
|
|
177
|
+
what it was last seen doing, such as the lock it was waiting on and the session
|
|
178
|
+
that held it.
|
|
179
|
+
|
|
180
|
+
## The local database keeps its data in Testkit's volume, whatever the image's tag
|
|
181
|
+
|
|
182
|
+
Testkit chose where to mount the local PostgreSQL container's named volume from
|
|
183
|
+
a major version it read out of the image's tag
|
|
184
|
+
([gfdelarue/testkit#481](https://github.com/gfdelarue/testkit/issues/481)). A tag
|
|
185
|
+
that only looked like a version, such as `team-db:33ab` on a PostgreSQL 16
|
|
186
|
+
image, got PostgreSQL 18's mount, `/var/lib/postgresql`. The cluster then lived
|
|
187
|
+
in an anonymous volume that Docker mounted at the image's
|
|
188
|
+
`/var/lib/postgresql/data`, so a recreated container started empty, and
|
|
189
|
+
removing the container deleted the data. A PostgreSQL 18 image whose tag read
|
|
190
|
+
below 18 got the older mount, and its container never became ready.
|
|
191
|
+
|
|
192
|
+
Testkit now reads the image's own configuration with `docker image inspect`:
|
|
193
|
+
its `PGDATA` and the volumes it declares. It pulls the image first when it
|
|
194
|
+
isn't local. The named volume takes the place of the deepest declared volume
|
|
195
|
+
that holds `PGDATA`, or mounts at `PGDATA` when no declared volume holds it.
|
|
196
|
+
Testkit stops with an error rather than guess when the image sets no `PGDATA`,
|
|
197
|
+
sets a relative one, or declares a volume inside it:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
Testkit cannot tell where image team-db:33ab keeps its PostgreSQL data: its configuration sets no PGDATA. Use an image built from the official postgres image, or set PGDATA in it.
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
A container that an earlier version mounted in the wrong place is recreated on
|
|
204
|
+
a fresh named volume, so its database starts empty once.
|
|
205
|
+
|
|
206
|
+
## A crashed run no longer blocks the next one after Windows reuses its PID
|
|
207
|
+
|
|
208
|
+
On Windows, once a crashed run's processes had ended and Windows had given one
|
|
209
|
+
of their process IDs to another process, the next run, `testkit cleanup` and
|
|
210
|
+
`testkit run stop` failed:
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
Application service process creation identity no longer matches pid 6944; refusing unsafe cleanup
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The crashed run's record stayed until the unrelated process exited
|
|
217
|
+
([gfdelarue/testkit#485](https://github.com/gfdelarue/testkit/issues/485)).
|
|
218
|
+
Linux and macOS could hit the same error when the new process led its own
|
|
219
|
+
process group.
|
|
220
|
+
|
|
221
|
+
A recorded process whose PID now belongs to a different process has ended.
|
|
222
|
+
Testkit leaves the new process alone and clears the crashed run's record. It
|
|
223
|
+
still refuses to signal a live process whose creation identity it can't read.
|
|
224
|
+
|
|
225
|
+
## The local database is ready when it accepts a connection from the host
|
|
226
|
+
|
|
227
|
+
Testkit waited for its local Postgres container by running `pg_isready` inside
|
|
228
|
+
it through `docker exec`, up to about once a second. On Docker Desktop each
|
|
229
|
+
exec costs about 0.17 s of the WSL VM's CPU, and a cold start ran seven or
|
|
230
|
+
eight of them.
|
|
231
|
+
|
|
232
|
+
Testkit now waits by connecting to the container's published port on
|
|
233
|
+
`127.0.0.1`, the address the services use, with the startup, authentication
|
|
234
|
+
and `SELECT 1` of its database checks. It tries every 10 to 100 ms, gives each
|
|
235
|
+
attempt 5 seconds, and still gives up after 60 seconds. A port that accepts the
|
|
236
|
+
connection but doesn't answer as PostgreSQL, as Docker Desktop's port proxy
|
|
237
|
+
does before Postgres listens, and a server that rejects the startup, such as
|
|
238
|
+
one still starting, don't count as ready. When readiness times out, the error
|
|
239
|
+
gives the last check's reason. A server that refuses the configured user or
|
|
240
|
+
password, or has no `postgres` database, fails at once with that reason instead
|
|
241
|
+
of waiting out the 60 seconds.
|
|
242
|
+
|
|
243
|
+
Testkit waits on the published port only when it reaches Docker through a
|
|
244
|
+
local socket or named pipe, whether `DOCKER_HOST`, `DOCKER_CONTEXT` or the
|
|
245
|
+
configuration's current context names it. A daemon behind a `tcp://` or `ssh://`
|
|
246
|
+
endpoint, at any address, can publish ports in another network namespace, as
|
|
247
|
+
Docker-in-Docker does, so readiness there still runs `pg_isready` in the
|
|
248
|
+
container. Through a local socket, Testkit runs that probe as well, at most once
|
|
249
|
+
a second, when nothing answers on the port: the connection is refused, an
|
|
250
|
+
attempt gets no reply, or what answers isn't PostgreSQL. After 10 seconds it
|
|
251
|
+
probes on any failed attempt. When the probe finds the server ready, readiness
|
|
252
|
+
succeeds. A socket that forwards to a daemon in another namespace works this
|
|
253
|
+
way. As before, the database URL Testkit gives tests names `127.0.0.1` and the
|
|
254
|
+
published port, which such a daemon doesn't serve on this host.
|
|
255
|
+
|
|
256
|
+
## Managed Chromium runs with its sandbox on
|
|
257
|
+
|
|
258
|
+
Playwright starts Chromium with `--no-sandbox` unless `chromiumSandbox` is
|
|
259
|
+
`true`, and Testkit didn't set it. Every UI file ran without Chromium's
|
|
260
|
+
sandbox, so a compromised renderer ran with the user's access to the checkout,
|
|
261
|
+
SSH keys and env files
|
|
262
|
+
([gfdelarue/testkit#190](https://github.com/gfdelarue/testkit/issues/190)).
|
|
263
|
+
|
|
264
|
+
Testkit now sets `chromiumSandbox: true` in the Playwright config it generates
|
|
265
|
+
and in the managed test's launch options. It holds whether a file imports
|
|
266
|
+
`test` from `@playwright/test`, `playwright/test`, or
|
|
267
|
+
`@gfdelarue/testkit/playwright`, when a project or a file sets other
|
|
268
|
+
`launchOptions`, and for browsers that `globalSetup` and `globalTeardown`
|
|
269
|
+
launch. An explicit `chromiumSandbox: false` in `playwright.config.ts` or in a
|
|
270
|
+
file's `test.use` still turns it off.
|
|
271
|
+
|
|
272
|
+
On a host that can't start the sandbox, such as root in a container, Chromium
|
|
273
|
+
now fails to launch. Testkit reports that as an infrastructure failure and puts
|
|
274
|
+
the opt-out first:
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
Testkit starts managed Chromium with its sandbox on, and this host can't start it. To run without the sandbox here, set use.launchOptions.chromiumSandbox to false in playwright.config.ts, or in one file with test.use.
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
[Browser launch options](engines.md#browser-launch-options) shows how to turn
|
|
281
|
+
it off for one host.
|
|
282
|
+
|
|
283
|
+
## Managed Chromium no longer crashes at launch under older glibc
|
|
284
|
+
|
|
285
|
+
Chromium sometimes crashed with `SIGSEGV` in `libdbus` during
|
|
286
|
+
`browserType.launch` on Ubuntu 24.04, and the UI file failed
|
|
287
|
+
([gfdelarue/testkit#453](https://github.com/gfdelarue/testkit/issues/453)).
|
|
288
|
+
At startup, Chromium sets `FC_FONTATIONS` on a worker thread while its D-Bus
|
|
289
|
+
thread reads the environment. glibc before 2.41 can move the environment and
|
|
290
|
+
free the old copy under that reader, unless the distribution backported the
|
|
291
|
+
fix. Ubuntu 24.04's glibc 2.39 hasn't.
|
|
292
|
+
|
|
293
|
+
Playwright files now run with `DBUS_SESSION_BUS_ADDRESS=disabled:` and
|
|
294
|
+
`FC_FONTATIONS=1`, the values Chromium sets itself. Chromium finds both already
|
|
295
|
+
set and doesn't grow the environment at startup.
|
|
296
|
+
|
|
297
|
+
- Tests, and any process or browser they start, see both variables.
|
|
298
|
+
- A `launchOptions.env` in `playwright.config.ts` or in a file's `test.use`
|
|
299
|
+
gets both added, under its own values. A browser that a test or global setup
|
|
300
|
+
launches directly with its own `env` gets only what that sets.
|
|
301
|
+
- The Playwright engine reserves both keys, so a group's environment can't set
|
|
302
|
+
them.
|
|
303
|
+
|
|
304
|
+
## A capture records only requests sent to its url
|
|
305
|
+
|
|
306
|
+
An HTTP capture recorded a request to any path outside `/__testkit__/` from any
|
|
307
|
+
caller that found its port, whatever its `Host` header
|
|
308
|
+
([gfdelarue/testkit#193](https://github.com/gfdelarue/testkit/issues/193)).
|
|
309
|
+
Another local user, or a web page through DNS rebinding, could add captures and
|
|
310
|
+
push real ones out of the list.
|
|
311
|
+
|
|
312
|
+
A capture's `url` now holds an unguessable segment, as its `requestsUrl`
|
|
313
|
+
already did, such as `http://127.0.0.1:41000/__testkit__/<segment>/webhook`.
|
|
314
|
+
The capture records a request only when its path starts with that segment, and
|
|
315
|
+
answers any other path with 404. A captured request's `path` leaves the segment
|
|
316
|
+
out, so a test that checks `path` still sees `/webhook`. The capture answers
|
|
317
|
+
403 to a request whose `Host` header isn't `127.0.0.1:<port>`. Testkit keeps
|
|
318
|
+
the new segment out of the run's records. A capture's `path` may no longer
|
|
319
|
+
contain `.` or `..` segments, because a client would resolve them against the
|
|
320
|
+
`url` and drop the segment.
|
|
321
|
+
|
|
322
|
+
If your product builds a URL from the capture's origin, give it the whole `url`
|
|
323
|
+
and append to that instead. [Handles](../README.md#handles) describes the
|
|
324
|
+
capture.
|
|
325
|
+
|
|
326
|
+
## Tokens, temporary files, results and Git calls are harder to reach
|
|
327
|
+
|
|
328
|
+
These changes keep another bug, or another user on a shared host, from reaching
|
|
329
|
+
what Testkit handles
|
|
330
|
+
([gfdelarue/testkit#196](https://github.com/gfdelarue/testkit/issues/196)).
|
|
331
|
+
|
|
332
|
+
- On Linux and macOS, `.testkit` is now private to its owner. Loading the
|
|
333
|
+
config and starting a run create it with mode `0700`, and any command that
|
|
334
|
+
resolves the product removes group and other access from an existing one the
|
|
335
|
+
user owns. Sealed objects are `0400` instead of `0444`. Another user, such as
|
|
336
|
+
a host user reading results that a container wrote as root, now needs the
|
|
337
|
+
owner to share them. On Windows, `.testkit` keeps the access its parent
|
|
338
|
+
folder grants.
|
|
339
|
+
- Services and setup steps no longer inherit `GITHUB_TOKEN`, `GH_TOKEN` or
|
|
340
|
+
`GITEA_TOKEN` from Testkit's environment. Testkit reads them itself for
|
|
341
|
+
known-failure checks and bug filing. A service that needs one declares it in
|
|
342
|
+
its `env`.
|
|
343
|
+
- Lint's `git ls-files` and bug filing's `git diff` no longer run the command
|
|
344
|
+
that the repository's `core.fsmonitor` names. Run fingerprinting already
|
|
345
|
+
turned it off.
|
|
346
|
+
- The `testkit-engine-*` directories that Testkit creates in the system's
|
|
347
|
+
temporary directory, which hold each browser profile, now record their
|
|
348
|
+
owner. The first engine invocation of a Testkit process removes those whose
|
|
349
|
+
owner has exited, such as after a crash. On Linux it only removes those from
|
|
350
|
+
its own PID namespace, so a container that shares the temporary directory
|
|
351
|
+
with its host leaves the host's alone, and the reverse. Directories from
|
|
352
|
+
earlier versions have no record and stay.
|
|
353
|
+
- On Linux, a recorded process identity now includes the boot ID, so after a
|
|
354
|
+
reboot a run or lock record no longer matches an unrelated process that got
|
|
355
|
+
the same PID and start time. A record from an earlier Testkit still matches on
|
|
356
|
+
start time alone, as before.
|
|
357
|
+
|
|
358
|
+
## A Playwright companion decides a Next app's support files
|
|
359
|
+
|
|
360
|
+
In a Next application, `testkit typecheck` added `next-env.d.ts`,
|
|
361
|
+
`tests/playwright-fixtures`, and the generated types under `.next` and
|
|
362
|
+
`.next-testkit` to the Playwright program even when a `tsconfig.playwright.json`
|
|
363
|
+
left them out or excluded them
|
|
364
|
+
([gfdelarue/testkit#108](https://github.com/gfdelarue/testkit/issues/108)). A
|
|
365
|
+
fixture the companion excluded, or another service's stale build output, could
|
|
366
|
+
then fail the check. With a companion, the program now holds the discovered
|
|
367
|
+
suites, the Playwright config, the files the companion selects, and what they
|
|
368
|
+
import. List the Next files the suites need in the companion. Without a
|
|
369
|
+
companion, the Next defaults stay.
|
|
370
|
+
|
|
371
|
+
## `typecheck` checks test files outside the tsconfig's `rootDir`
|
|
372
|
+
|
|
373
|
+
The generated programs took `rootDir` and `outDir` from the tsconfig they
|
|
374
|
+
extend. A test file outside that `rootDir`, such as `tests/sum.test.ts` beside a
|
|
375
|
+
tsconfig whose `rootDir` is `src`, failed `typecheck` with `TS6059` before any of
|
|
376
|
+
its types were checked. TypeScript 6 also defaults `rootDir` to the directory of
|
|
377
|
+
the tsconfig it compiles, which is Testkit's generated one, so under TypeScript 6
|
|
378
|
+
every test file failed when the tsconfig set `outDir` and no `rootDir`
|
|
379
|
+
([gfdelarue/testkit#407](https://github.com/gfdelarue/testkit/issues/407)).
|
|
380
|
+
|
|
381
|
+
The generated configs now clear the inherited output paths, `outDir`,
|
|
382
|
+
`outFile`, `declarationDir`, `sourceRoot`, and `mapRoot`, and the test programs'
|
|
383
|
+
configs clear `rootDir` too. TypeScript holds every file to an explicit
|
|
384
|
+
`rootDir`, and when an output path is set without one, TypeScript 6 uses the
|
|
385
|
+
tsconfig's own directory. With both cleared, it holds test files to neither. When the tsconfig sets `incremental` or `composite`,
|
|
386
|
+
Testkit now writes its build info beside the generated config in
|
|
387
|
+
`.testkit/_typecheck`, instead of under the repository's `outDir` or into the
|
|
388
|
+
repository's own build info file.
|
|
389
|
+
|
|
390
|
+
## A run stops its retained database when it releases it
|
|
391
|
+
|
|
392
|
+
A run that provisioned the local Postgres container now stops it as part of releasing the run's resources, after it drops the run's task databases. It stops the container by the name in `.testkit/_infra/local-postgres` and lists no Docker resources to do it. A container that is already stopped counts as released.
|
|
393
|
+
|
|
394
|
+
If that container no longer exists, the release fails, and so does the run, with `Could not stop the retained database container <name>: it no longer exists`. Before, a successful run stopped the container later, during finish-time maintenance.
|
|
395
|
+
|
|
396
|
+
## A run leaves Docker resources to `testkit cleanup`
|
|
397
|
+
|
|
398
|
+
A run's start and its post-run maintenance no longer list Docker resources, remove unreferenced containers and volumes, or stop the retained database. Provisioning and release still create, replace, and remove what the run needs, and release stops the retained database by name. `testkit cleanup --resources` removes the product's unreferenced containers and volumes, and stops an idle retained database, as before.
|
|
399
|
+
|
|
400
|
+
A run's start still removes stale manifests of runs whose processes have ended, and post-run maintenance still removes other runs' stale manifests.
|
|
401
|
+
|
|
402
|
+
`.testkit/results/maintenance.json` no longer has the `removed`, `skipped` and `stopped` lists, since maintenance no longer removes or stops Docker resources.
|
|
403
|
+
|
|
404
|
+
## `run.json`'s storage inventory covers only `.testkit/results`
|
|
405
|
+
|
|
406
|
+
`run.json`'s `storage.testkit` inventory now covers only `.testkit/results`, and its `root` is `.testkit/results`. A run no longer walks the database and graph caches to build it. When Testkit can't read part of `.testkit/results`, `run.json` records `"storage": { "testkit": { "status": "failed", "error": "…" } }` and the run keeps its result.
|
|
407
|
+
|
|
408
|
+
## Testkit's own clients of the owned database run inside its container
|
|
409
|
+
|
|
410
|
+
Testkit used to start a client container, from `postgres:16` or
|
|
411
|
+
`TESTKIT_POSTGRES_CLIENT_IMAGE`, to declare roles and take schema snapshots in
|
|
412
|
+
the database it owns. Before a snapshot, it also asked the server for its
|
|
413
|
+
version to choose a `pg_dump` image. Both now run inside the database container
|
|
414
|
+
with `docker exec`, using the database image's own `psql` and `pg_dump`, as
|
|
415
|
+
Testkit's admin queries already did. They no longer start a container
|
|
416
|
+
([gfdelarue/testkit#139](https://github.com/gfdelarue/testkit/issues/139)).
|
|
417
|
+
|
|
418
|
+
This changes two things:
|
|
419
|
+
|
|
420
|
+
- `TESTKIT_POSTGRES_CLIENT_IMAGE` no longer applies to those operations. Your
|
|
421
|
+
SQL, in `sql-file` steps and `database-steps` helpers, still runs in a client
|
|
422
|
+
container from that image, and so do clients of external databases.
|
|
423
|
+
- The `image` that `database.postgres()` uses must include `psql` and
|
|
424
|
+
`pg_dump`, and its `pg_dump` must be at least as new as its server.
|
|
425
|
+
Otherwise the operation fails with a message that names the image:
|
|
426
|
+
|
|
427
|
+
```text
|
|
428
|
+
pg_dump in the database image <image> is older than its server: pg_dump: error: aborting because of server version mismatch
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Redaction recognises more secret names, API key headers, and bearer tokens
|
|
432
|
+
|
|
433
|
+
Sealing, filed bugs, and error messages kept a secret under a key such as
|
|
434
|
+
`STRIPE_KEY`, `GITHUB_PAT`, `SMTP_PASS`, or `SENTRY_DSN`, and the value of an
|
|
435
|
+
`X-Api-Key` header or an `apiKey` member. They kept a bearer token outside an
|
|
436
|
+
`Authorization` header, and a header that a trace stores as a
|
|
437
|
+
`{"name": …, "value": …}` pair
|
|
438
|
+
([gfdelarue/testkit#188](https://github.com/gfdelarue/testkit/issues/188)).
|
|
439
|
+
|
|
440
|
+
- A key whose last word is `PASS`, `PASSWD`, `PAT`, `DSN`, `CREDENTIAL`, or
|
|
441
|
+
`CREDENTIALS` now names a secret, as does a key whose last two words are
|
|
442
|
+
`API` and `KEY`. An upper-case key whose last word is `KEY` names a secret
|
|
443
|
+
unless the word before it is `PUBLIC` or `PUBLISHABLE`. A run's environment
|
|
444
|
+
values under these keys are redacted as other secrets are, so a value under
|
|
445
|
+
a key such as `CACHE_KEY` is now redacted too. `PATH`, `BYPASS`, and
|
|
446
|
+
`cacheKey` still name no secret.
|
|
447
|
+
- `Api-Key` and `X-Api-Key` header values are redacted like `Authorization`.
|
|
448
|
+
- The token after `Bearer` is redacted wherever it appears when it is at least
|
|
449
|
+
eight characters long and holds a digit, so prose such as
|
|
450
|
+
`Bearer authentication` stays.
|
|
451
|
+
- In a `name` and `value` pair, the value is redacted when the name names a
|
|
452
|
+
secret, such as `Authorization` or `Cookie`. When `testkit run` stores a
|
|
453
|
+
result, every value in a `cookies` array is redacted too.
|
|
454
|
+
|
|
455
|
+
`docs/bug-records.md` lists the rules.
|
|
456
|
+
|
|
457
|
+
## Redaction recognises more secret forms and fewer ordinary words
|
|
458
|
+
|
|
459
|
+
Sealing, filed bugs, and error messages kept these secrets
|
|
460
|
+
([gfdelarue/testkit#215](https://github.com/gfdelarue/testkit/issues/215)):
|
|
461
|
+
|
|
462
|
+
- A `privateKey`, `signingKey`, or `encryptionKey` value.
|
|
463
|
+
- A single-quoted member under any secret name other than `password`, as in
|
|
464
|
+
`{'token': '…'}`.
|
|
465
|
+
- The strings in a JSON array or object under a secret name, as in
|
|
466
|
+
`{"tokens":["…"]}`. `session` and `auth` settings stay, and an object with a
|
|
467
|
+
`name` and a `value` member loses only its `value` and members under a secret
|
|
468
|
+
name.
|
|
469
|
+
- A value after `password:`. A quoted value is redacted anywhere, and an
|
|
470
|
+
unquoted one when it is the one word of a line that it starts. A single word
|
|
471
|
+
of letters stays, so `password: 'Required'` and `password: required!` stay.
|
|
472
|
+
- A URL password that holds a `/`, a URL password in a directory name, such as
|
|
473
|
+
`postgres:/app:…@db`, and a token of at least 20 characters with a digit that
|
|
474
|
+
stands alone as the user of an `http` or `https` URL, as in
|
|
475
|
+
`https://ghp_…@github.com`. A resolved URL's password or token is redacted
|
|
476
|
+
wherever it appears, too.
|
|
477
|
+
- A secret right after another one with no space between them, as in
|
|
478
|
+
`PASSWORD=…"Cookie: sid=…`.
|
|
479
|
+
- A URL password that output cut short. The first line of a task's output, as
|
|
480
|
+
an artifact summary or a failure message, is redacted before Testkit cuts it.
|
|
481
|
+
|
|
482
|
+
They redacted these values that are not secrets:
|
|
483
|
+
|
|
484
|
+
- A value under `author`, `authority`, or `GIT_AUTHOR_NAME`, and under
|
|
485
|
+
`sessionCount`, `SESSION_TIMEOUT`, and other keys where `SESSION` comes before
|
|
486
|
+
a count or a time. A run's environment no longer redacts every occurrence of
|
|
487
|
+
`GIT_AUTHOR_NAME`'s value either.
|
|
488
|
+
- A path assigned to a key that ends in `_URL`, such as
|
|
489
|
+
`AUTH_URL=/oauth/authorize`. A `token=` parameter in the path is still
|
|
490
|
+
redacted. A JSON member such as `{"AUTH_URL":"/oauth/authorize"}` is still
|
|
491
|
+
redacted whole.
|
|
492
|
+
- The text after a quoted header value that ends in an escaped backslash.
|
|
493
|
+
|
|
494
|
+
`testkit bug record` now rejects a record whose reproduce command holds text
|
|
495
|
+
that Testkit redacts, as `testkit bug file` already did. Before, a Vitest
|
|
496
|
+
project name such as `TOKEN=…` passed `bug record` and stopped `bug file`.
|
|
497
|
+
|
|
498
|
+
## Sealing redacts inside traces and other compressed files
|
|
499
|
+
|
|
500
|
+
Sealing didn't look inside `.zip` and `.gz` files. A Playwright `trace.zip`
|
|
501
|
+
recorded with `use.trace` kept form values, `Authorization` and `Cookie`
|
|
502
|
+
headers, and session cookies in the sealed run, compressed, while the run's
|
|
503
|
+
own copies of the same output were redacted
|
|
504
|
+
([gfdelarue/testkit#187](https://github.com/gfdelarue/testkit/issues/187)).
|
|
505
|
+
|
|
506
|
+
Sealing now reads `.zip` and `.gz` files, and files that start like one. It
|
|
507
|
+
redacts each text entry with the same rules as a text file and writes the
|
|
508
|
+
archive again, so the trace is kept and opens in the trace viewer with
|
|
509
|
+
`<redacted>` in place of the secrets. A text entry is valid UTF-8 without binary
|
|
510
|
+
control characters, or UTF-16 with a byte order mark. Entries it doesn't change
|
|
511
|
+
keep their bytes. A ZIP with nothing to redact and no comment or extra fields
|
|
512
|
+
stays byte for byte, and a gzip file is always written again without the name
|
|
513
|
+
and comment in its header.
|
|
514
|
+
|
|
515
|
+
- The bundle's redaction counts include the redacted archives: each counts as
|
|
516
|
+
a redacted file, its text entries count as scanned files, and its
|
|
517
|
+
replacements count too.
|
|
518
|
+
- Sealing refuses an archive it can't redact: one it can't read, such as an
|
|
519
|
+
encrypted, ZIP64, damaged, or larger than 512 MiB archive, one whose binary
|
|
520
|
+
entry holds a value the run resolved, in UTF-8 or UTF-16, or one that holds
|
|
521
|
+
another archive.
|
|
522
|
+
- Sealing removes each file it refuses, an archive or a binary file that holds
|
|
523
|
+
a resolved value, from the run's results. It fails the run with the reasons,
|
|
524
|
+
then seals the rest and records them. `testkit stop`, `testkit cleanup` and
|
|
525
|
+
the next run do the same when they seal a run that a killed process left.
|
|
526
|
+
Before, a refused run left its results in place, and those commands sealed
|
|
527
|
+
them without the values the run had resolved, the refused file included.
|
|
528
|
+
- Screenshots and video, in a trace or on their own, aren't redacted.
|
|
529
|
+
|
|
530
|
+
## Sealed bundles leave out the product and home directories
|
|
531
|
+
|
|
532
|
+
Sealing removed the product directory and host from `run.json`, but the rest of
|
|
533
|
+
the bundle kept them
|
|
534
|
+
([gfdelarue/testkit#189](https://github.com/gfdelarue/testkit/issues/189)). A
|
|
535
|
+
failing Playwright file's stack in `run.json`, the native report's `sourceFile`
|
|
536
|
+
and attachment paths, and a `trace.zip` held the absolute product path. A trace
|
|
537
|
+
also held the home directory, in the path of the Chromium that Testkit manages.
|
|
538
|
+
On a developer machine those paths name the user.
|
|
539
|
+
|
|
540
|
+
Sealing now rewrites local paths in the run record, in every text file of the
|
|
541
|
+
bundle, and in every text entry of a compressed file such as `trace.zip`. A
|
|
542
|
+
path under the product directory becomes relative to it, and a path under the
|
|
543
|
+
home directory starts with `~`. When sealing changes a file, by this rewrite or
|
|
544
|
+
by redaction, the file's size and SHA-256 in `run.json` now describe the sealed
|
|
545
|
+
file.
|
|
546
|
+
|
|
547
|
+
## An exit code set after a plain file's tests fails the run
|
|
548
|
+
|
|
549
|
+
When a reporter or global teardown set Vitest's exit code to 1 after a file's
|
|
550
|
+
tests failed, Testkit read the run as those failed tests alone
|
|
551
|
+
([gfdelarue/testkit#215](https://github.com/gfdelarue/testkit/issues/215)). A
|
|
552
|
+
run whose failed tests all had issues passed the known-failure gate under
|
|
553
|
+
`"allow"`, though something else had also failed it.
|
|
554
|
+
|
|
555
|
+
Testkit now notes Vitest's own verdict when the tests end, and fails the run
|
|
556
|
+
with a run error when a reporter or global teardown sets the exit code
|
|
557
|
+
afterwards:
|
|
558
|
+
|
|
559
|
+
```text
|
|
560
|
+
FAIL run error
|
|
561
|
+
Vitest failed the run after its tests finished: exit code 1 while Vitest closed
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
When the tests passed, the run error says "after its tests passed", as it does
|
|
565
|
+
for a coverage threshold, and each file keeps its own outcome. Before, such an
|
|
566
|
+
exit failed every file as an unexplained infrastructure failure. A coverage
|
|
567
|
+
threshold that falls short beside a failed test still counts as part of that
|
|
568
|
+
failure, because a failed test leaves code unrun.
|
|
569
|
+
|
|
570
|
+
## The known-failure gate stops missing three failures
|
|
571
|
+
|
|
572
|
+
Three failures could pass the known-failure gate under `"allow"`, or never be
|
|
573
|
+
known at all
|
|
574
|
+
([gfdelarue/testkit#215](https://github.com/gfdelarue/testkit/issues/215)):
|
|
575
|
+
|
|
576
|
+
- A plain Vitest file whose data-flow evidence was malformed lost that error
|
|
577
|
+
when one of its tests also failed. The file now fails with the evidence
|
|
578
|
+
error beside its failed tests, which an issue for the tests doesn't cover.
|
|
579
|
+
- A Playwright spec that failed in another file, such as a dependency or
|
|
580
|
+
teardown project, now always counts as a failure that names no test, even
|
|
581
|
+
when the run reports nothing else about it.
|
|
582
|
+
- On macOS and Linux, a test file whose name holds a backslash could not be
|
|
583
|
+
filed, and its failures were always new. A bug record now keeps the
|
|
584
|
+
backslash, and treats it as a separator only on Windows.
|
|
585
|
+
|
|
586
|
+
Testkit reads the file a Playwright spec was loaded from out of its file
|
|
587
|
+
suite's title, resolved against `rootDir`. It now checks, as the run begins,
|
|
588
|
+
that each title names a file. If a Playwright release changes the title so that
|
|
589
|
+
it names no file, the file fails with an error that says so, instead of
|
|
590
|
+
reporting the spec under a path where no file exists.
|
|
591
|
+
|
|
592
|
+
## Four Playwright failures stop passing as known
|
|
593
|
+
|
|
594
|
+
Four Playwright failures could pass the known-failure gate under `"allow"`, or
|
|
595
|
+
never be known at all
|
|
596
|
+
([gfdelarue/testkit#215](https://github.com/gfdelarue/testkit/issues/215)):
|
|
597
|
+
|
|
598
|
+
- A reporter in the Playwright config that ended the process with exit code 1
|
|
599
|
+
read as Playwright's own exit for failed specs, so an issue for those specs
|
|
600
|
+
covered the run. Testkit's reporter runs last and marks the run once every
|
|
601
|
+
reporter's hooks have returned. Without that mark, exit code 1 is a failure
|
|
602
|
+
that names no test. A `PLAYWRIGHT_SPECS_FAILED` failure carries
|
|
603
|
+
`reportersFinished` in its details. A run stored by an earlier release has no
|
|
604
|
+
such mark, so `testkit ci report` reads its exit code 1 the same way. A
|
|
605
|
+
Playwright config that sets `PW_TEST_REPORTER` now fails, because Playwright
|
|
606
|
+
runs that reporter after Testkit's.
|
|
607
|
+
- A failed spec in a serial group, or a failed `beforeAll` hook, could stop
|
|
608
|
+
later specs of the selected file. Playwright reports those specs as skipped,
|
|
609
|
+
so an issue for the failed spec let the run pass. Each such spec is now a
|
|
610
|
+
detail of kind `playwright-not-run`, which names no test. A spec that the
|
|
611
|
+
file skips with `test.skip` or `test.fixme` is not one. A spec that a run
|
|
612
|
+
stops at `maxFailures` gets the same detail, though that run already failed
|
|
613
|
+
the gate on the error Playwright reports when it stops.
|
|
614
|
+
- Under `failOnFlakyTests`, a spec that passed only on a retry failed the run
|
|
615
|
+
as a failure that names no test, so no issue could cover it. It is now a
|
|
616
|
+
`playwright-spec` detail with its title, and an issue for that title covers
|
|
617
|
+
it.
|
|
618
|
+
- A file whose every spec came from one helper with another extension, such
|
|
619
|
+
as a `.ts` file and a `.mjs` helper, ran no specs and failed with
|
|
620
|
+
`PLAYWRIGHT_NO_TESTS`. Playwright moves the file suite's location to that
|
|
621
|
+
helper, and Testkit selected the file by location. Testkit now selects it
|
|
622
|
+
with `--grep` on its file suite's title, the file's path from `rootDir`, so
|
|
623
|
+
its specs run.
|
|
624
|
+
|
|
625
|
+
## Tracker tokens go only where they belong
|
|
626
|
+
|
|
627
|
+
Five gaps in how Testkit talks to GitHub and Gitea are closed
|
|
628
|
+
([gfdelarue/testkit#215](https://github.com/gfdelarue/testkit/issues/215)):
|
|
629
|
+
|
|
630
|
+
- `GITEA_TOKEN` names no host, so Testkit sent it to whichever Gitea host the
|
|
631
|
+
checkout's remote named. Outside a Gitea Actions job, Testkit now sends it
|
|
632
|
+
only to the host that `GITEA_SERVER_URL` names. Set
|
|
633
|
+
`GITEA_SERVER_URL=https://gitea.example.com` beside `GITEA_TOKEN`, or keep the
|
|
634
|
+
token in a Git credential helper, which is bound to its host already.
|
|
635
|
+
- Testkit sends a token only over HTTPS. A plain `http://` remote or repository
|
|
636
|
+
URL now fails with a message that says so, unless it names a loopback host.
|
|
637
|
+
- `testkit ci report` updated the first pull request comment that started with
|
|
638
|
+
its marker, whoever wrote it. It now updates only a comment written by its
|
|
639
|
+
token's user. It takes that user from the commit status it has just set, or
|
|
640
|
+
asks the tracker when the status names no one. When neither names the user,
|
|
641
|
+
it posts a new comment each time rather than edit one.
|
|
642
|
+
- When the tracker created an issue without its labels, `testkit bug file`
|
|
643
|
+
failed and left the issue open. It now closes that issue first, and says
|
|
644
|
+
whether it could.
|
|
645
|
+
- `testkit ci report` now leaves out of the summary and the commit status any CI
|
|
646
|
+
run or issue link that holds credentials or a secret.
|
|
647
|
+
|
|
648
|
+
## `bug file` asks the remote for the commit, and closes a duplicate it filed
|
|
649
|
+
|
|
650
|
+
Two gaps in `testkit bug file` are closed, along with a Gitea problem that the
|
|
651
|
+
second turned up ([gfdelarue/testkit#215](https://github.com/gfdelarue/testkit/issues/215)):
|
|
652
|
+
|
|
653
|
+
- It took the commit as pushed when a local remote-tracking branch held it,
|
|
654
|
+
even after the remote rewound or deleted that branch. It now lists the
|
|
655
|
+
remote's branches with `git ls-remote` and checks their tips, fetching a tip
|
|
656
|
+
the checkout lacks. A renamed branch still counts. When a remote doesn't
|
|
657
|
+
answer, or a shallow clone's history stops before Git can tell, Testkit
|
|
658
|
+
stops and says why, unless another remote has the commit.
|
|
659
|
+
- Two checkouts that filed the same test at once could each create an issue,
|
|
660
|
+
because neither saw the other's in the open issues it read first. After it
|
|
661
|
+
creates the issue, Testkit now records it in the draft and reads the open
|
|
662
|
+
issues again. GitHub can list a new issue late, so it waits up to 7.5 seconds
|
|
663
|
+
for its own to appear, and on GitHub it then reads again two seconds later.
|
|
664
|
+
It says so when its issue never appears. When an older open issue covers the
|
|
665
|
+
same test, Testkit closes its own, comments with the older one's number, and
|
|
666
|
+
stops as it would have if it had seen that issue first.
|
|
667
|
+
- On Gitea, two checkouts creating the same label at once made two labels of
|
|
668
|
+
that name, and Gitea's label filter then returned no issue. Testkit now
|
|
669
|
+
deletes a label it created when an older one has the same name, and lists
|
|
670
|
+
the open bugs without the filter when the repository already has two labels
|
|
671
|
+
of one name.
|
|
672
|
+
|
|
673
|
+
## A failed database drop no longer hides the error before it
|
|
674
|
+
|
|
675
|
+
When a template step failed, Testkit dropped the half-built template database
|
|
676
|
+
before it reported the step's error. If the drop failed too, the run reported
|
|
677
|
+
only the drop's error. A run interrupted during a template `sql-file` step,
|
|
678
|
+
after its Docker connection had closed, reported only `Cannot connect to the
|
|
679
|
+
Docker daemon`, and nothing about the step or the Postgres client container it
|
|
680
|
+
left running
|
|
681
|
+
([gfdelarue/testkit#400](https://github.com/gfdelarue/testkit/issues/400)). A
|
|
682
|
+
`resetBefore` file whose database clone failed had the same problem.
|
|
683
|
+
|
|
684
|
+
The run now reports both errors, and names the database Testkit couldn't drop:
|
|
685
|
+
|
|
686
|
+
```text
|
|
687
|
+
Dockerized Postgres client was cancelled
|
|
688
|
+
Postgres client container cleanup failed: Cannot connect to the Docker daemon at tcp://127.0.0.1:36893. Is the docker daemon running?
|
|
689
|
+
Dropping the template database tk_tpl_api_f14201a8f06684a4 also failed: Cannot connect to the Docker daemon at tcp://127.0.0.1:36893. Is the docker daemon running?
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
## A failure block prints each message once, without color codes
|
|
693
|
+
|
|
694
|
+
A failed Playwright assertion printed its message twice in the run's failure
|
|
695
|
+
block, once for the test and once for Playwright's overall failure. Both copies
|
|
696
|
+
kept Playwright's ANSI color codes, even with `NO_COLOR` set, and both were cut
|
|
697
|
+
off mid-word
|
|
698
|
+
([gfdelarue/testkit#220](https://github.com/gfdelarue/testkit/issues/220)).
|
|
699
|
+
|
|
700
|
+
The block now strips the engine's color codes, prints each distinct message
|
|
701
|
+
once, and says how much of a long message it left out. It cuts at a space when
|
|
702
|
+
one falls within 40 characters of the limit, and otherwise at the limit, without
|
|
703
|
+
splitting a character:
|
|
704
|
+
|
|
705
|
+
```text
|
|
706
|
+
[1/1] FAIL app ui __testkit__/failure.ui.testkit.ts 3s
|
|
707
|
+
Error: expect(locator).toHaveText(expected) failed Locator: locator('#status') Expected:
|
|
708
|
+
"expected marker" Received: "actual" Timeout: 1000ms Call log: - Expect "toHaveText" with
|
|
709
|
+
timeout 1000ms - waiting for locator('#status') 5 × locator … (69 more characters)
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
The run's failure details keep the full message. The block's second and later
|
|
713
|
+
messages are now redacted like the first.
|
|
714
|
+
|
|
715
|
+
## Long command output no longer warns about listeners
|
|
716
|
+
|
|
717
|
+
Commands write their text output one `log` call at a time, usually a line each,
|
|
718
|
+
and each call added an `error` listener to stdout until its write finished. More
|
|
719
|
+
than ten calls in a row, as in a longer `discover`, `status`, `artifacts`, or
|
|
720
|
+
`workspace` listing, printed `MaxListenersExceededWarning` on stderr
|
|
721
|
+
([gfdelarue/testkit#221](https://github.com/gfdelarue/testkit/issues/221)).
|
|
722
|
+
Testkit now adds one listener.
|
|
723
|
+
|
|
724
|
+
## Testkit's runtime keys take the `@gfdelarue/testkit` prefix
|
|
725
|
+
|
|
726
|
+
Three keys that Testkit's modules use to share state inside an engine process
|
|
727
|
+
had kept the old `elench.testkit.*` names
|
|
728
|
+
([gfdelarue/testkit#99](https://github.com/gfdelarue/testkit/issues/99)). They
|
|
729
|
+
are now `@gfdelarue/testkit/node-vitest-runtime-input/v1`,
|
|
730
|
+
`@gfdelarue/testkit/node-vitest-runtime-task/v1` and
|
|
731
|
+
`@gfdelarue/testkit/engine-process-environment-overlay/v1`.
|
|
732
|
+
|
|
733
|
+
There is nothing to do when you upgrade. Testkit writes the keys afresh for
|
|
734
|
+
every invocation, stored runs don't hold them, and the CLI refuses to run when
|
|
735
|
+
the product's installed Testkit is a different version, so both sides always
|
|
736
|
+
come from one release. Code that read these undocumented globals directly needs
|
|
737
|
+
the new names. The `com.elench.testkit.*` Docker labels are unchanged.
|
|
738
|
+
|
|
739
|
+
## `bug file --batch` files several bugs in one call
|
|
740
|
+
|
|
741
|
+
`testkit bug file --batch` files the drafts it is given, or every unfiled draft
|
|
742
|
+
when it is given none
|
|
743
|
+
([gfdelarue/testkit#254](https://github.com/gfdelarue/testkit/issues/254)). It
|
|
744
|
+
checks the checkout once, runs the drafts' tests together, and reports filed,
|
|
745
|
+
already filed, rejected, or not filed for each draft. It exits non-zero when
|
|
746
|
+
any draft is rejected or not filed, and a rerun files only what is left. A
|
|
747
|
+
campaign's pull request summary now suggests it for the bugs that are recorded
|
|
748
|
+
and not filed.
|
|
749
|
+
|
|
1
750
|
# 0.6.0
|
|
2
751
|
|
|
3
752
|
0.6.0 removes the `contract` and `data` test types and legacy service
|