@stacknext/playwright 0.9.0 → 0.10.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/docs/correlation.md +66 -0
- package/docs/fixture.md +83 -0
- package/docs/index.md +100 -0
- package/docs/troubleshooting.md +62 -0
- package/package.json +4 -3
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Correlation
|
|
3
|
+
description: Exact trace injection, probing and the verified/incomplete sample rule.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Correlation
|
|
7
|
+
|
|
8
|
+
StackNext never links browser and server activity by time or proximity. Each
|
|
9
|
+
sample is proven by an injected trace context.
|
|
10
|
+
|
|
11
|
+
## Injection
|
|
12
|
+
|
|
13
|
+
`createTraceparent()` generates a W3C `traceparent` with a new trace id and
|
|
14
|
+
span id. The fixture adds it to document, fetch and XHR requests whose URL is:
|
|
15
|
+
|
|
16
|
+
- loopback (`127.0.0.1`, `localhost`, `[::1]`, `::1`); or
|
|
17
|
+
- the Playwright project's `baseURL` origin.
|
|
18
|
+
|
|
19
|
+
Other resource types and cross-origin requests are left untouched.
|
|
20
|
+
|
|
21
|
+
## Verification
|
|
22
|
+
|
|
23
|
+
The collector considers a trace verified only when both are true:
|
|
24
|
+
|
|
25
|
+
1. it stored a trace with the injected trace id; and
|
|
26
|
+
2. it contains a server span whose parent span id equals the injected span id.
|
|
27
|
+
|
|
28
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
29
|
+
|
|
30
|
+
<!-- coderabbit-ai-generated-section:v1:35e306be3c7839621b0cb18396b64a12651243d1d324f2c17b11b03ca80b9e99 -->
|
|
31
|
+
|
|
32
|
+
The fixture probes `GET /api/traces/:traceId` until the
|
|
33
|
+
document trace is found or the timeout expires. It submits at most 20 trace
|
|
34
|
+
references per sample, document requests first.
|
|
35
|
+
|
|
36
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
37
|
+
|
|
38
|
+
If either condition is missing, the sample is `incomplete` with a reason such
|
|
39
|
+
as:
|
|
40
|
+
|
|
41
|
+
- `trace-not-found`;
|
|
42
|
+
- `injected-parent-not-found`;
|
|
43
|
+
- `no-request-trace-recorded`.
|
|
44
|
+
|
|
45
|
+
There is no fallback to a nearby request, a time window or a synthetic trace.
|
|
46
|
+
An incomplete sample makes the affected comparison inconclusive.
|
|
47
|
+
|
|
48
|
+
## Why the server must cooperate
|
|
49
|
+
|
|
50
|
+
`@stacknext/next` installs the W3C composite propagator during registration. If
|
|
51
|
+
the app does not run StackNext instrumentation, or another provider replaces the
|
|
52
|
+
propagator, the injected trace id never reaches the server and correlation
|
|
53
|
+
fails.
|
|
54
|
+
|
|
55
|
+
The collector's self-instrumentation filter also excludes requests to
|
|
56
|
+
`/__stacknext/`, so dashboard and MCP traffic cannot be mistaken for application
|
|
57
|
+
requests.
|
|
58
|
+
|
|
59
|
+
## Limits
|
|
60
|
+
|
|
61
|
+
- One worker only. Parallel correlation is not verified.
|
|
62
|
+
- Redirects and new tabs may create traces that are not in the submitted set.
|
|
63
|
+
- Browser-side rendering and network timing are not captured.
|
|
64
|
+
- Playwright screenshots, video and trace archives are never read or stored.
|
|
65
|
+
|
|
66
|
+
See [regression captures](../../regression/docs/captures.md).
|
package/docs/fixture.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Fixture
|
|
3
|
+
description: How the auto stacknextCapture fixture identifies scenarios and submits samples.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fixture
|
|
7
|
+
|
|
8
|
+
Import `test` and `expect` from `@stacknext/playwright` instead of
|
|
9
|
+
`@playwright/test`. The `stacknextCapture` fixture is automatic; you do not add
|
|
10
|
+
it to the test signature.
|
|
11
|
+
|
|
12
|
+
## Capture lifecycle
|
|
13
|
+
|
|
14
|
+
1. `resolveCaptureConfig()` reads the capture environment.
|
|
15
|
+
2. If capture is inactive, the fixture is a no-op.
|
|
16
|
+
3. During the test, document/fetch/XHR requests to loopback or the configured
|
|
17
|
+
`baseURL` origin receive a W3C `traceparent`.
|
|
18
|
+
4. After the test, the fixture waits for the collector to observe the traces.
|
|
19
|
+
5. It submits one sample with the Playwright status, duration, retry/repeat
|
|
20
|
+
indices and verified trace references.
|
|
21
|
+
|
|
22
|
+
Skipped tests do not submit a sample. The fixture never replaces Playwright
|
|
23
|
+
assertions or changes the test result.
|
|
24
|
+
|
|
25
|
+
## Scenario identity
|
|
26
|
+
|
|
27
|
+
The preferred identity is an explicit annotation:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { test, expect } from '@stacknext/playwright'
|
|
31
|
+
|
|
32
|
+
test('checkout completes', async ({ page }) => {
|
|
33
|
+
test.info().annotations.push({
|
|
34
|
+
type: 'stacknext.scenario',
|
|
35
|
+
description: 'checkout-complete',
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
await page.goto('/checkout')
|
|
39
|
+
await expect(page.getByRole('heading', { name: 'Checkout' })).toBeVisible()
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The fixture accepts any annotation whose type starts with `stacknext` and uses
|
|
44
|
+
its description. If none exists, identity falls back to the Playwright `testId`,
|
|
45
|
+
then file + title + project.
|
|
46
|
+
|
|
47
|
+
Keep the annotation stable. Changing it creates a new scenario with no matching
|
|
48
|
+
baseline.
|
|
49
|
+
|
|
50
|
+
## Capture environment
|
|
51
|
+
|
|
52
|
+
The fixture reads:
|
|
53
|
+
|
|
54
|
+
| Variable | Default | Meaning |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `STACKNEXT_TEST_RUN_ID` | required when active | Active `run-...` id. |
|
|
57
|
+
| `STACKNEXT_COLLECTOR_URL` | required when active | Loopback collector origin. |
|
|
58
|
+
| `STACKNEXT_TOKEN` | required when active | Collector bearer token. |
|
|
59
|
+
| `STACKNEXT_CAPTURE_SETTLE_MS` | 500 | Wait before the first probe. |
|
|
60
|
+
| `STACKNEXT_CAPTURE_TIMEOUT_MS` | 5000 | Probe deadline per sample. |
|
|
61
|
+
|
|
62
|
+
`stacknext capture` sets the required values. Do not set them by hand for a
|
|
63
|
+
normal captured run.
|
|
64
|
+
|
|
65
|
+
## Playwright configuration
|
|
66
|
+
|
|
67
|
+
- Use **one worker** for captured runs.
|
|
68
|
+
- Use at least three samples per scenario for a comparison
|
|
69
|
+
(`--repeat-each=3`).
|
|
70
|
+
- Warm routes before capturing a baseline.
|
|
71
|
+
- Keep the test command short and deterministic.
|
|
72
|
+
|
|
73
|
+
## Exports
|
|
74
|
+
|
|
75
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
76
|
+
|
|
77
|
+
<!-- coderabbit-ai-generated-section:v1:9b1d429fc146b7836cdccc75d58c560d2e60b18305797d98bcd9841b60c57664 -->
|
|
78
|
+
|
|
79
|
+
`stackNextFixtures()` is an exported function returning `{ test, expect }`. `resolveCaptureConfig()` returns a
|
|
80
|
+
`CaptureConfig` or `null`; it throws `CaptureTransportError` when capture is
|
|
81
|
+
active but the required values are invalid.
|
|
82
|
+
|
|
83
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@stacknext/playwright"
|
|
3
|
+
description: Optional Playwright fixtures that correlate browser scenarios with StackNext server telemetry.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @stacknext/playwright
|
|
7
|
+
|
|
8
|
+
`@stacknext/playwright` provides a drop-in Playwright `test` fixture. During
|
|
9
|
+
`stacknext capture`, it injects W3C trace context into browser requests, probes
|
|
10
|
+
the collector for the resulting server trace and submits verified samples for
|
|
11
|
+
the scenario.
|
|
12
|
+
|
|
13
|
+
## Who should read this
|
|
14
|
+
|
|
15
|
+
Teams using runtime regression testing. This is an **optional public
|
|
16
|
+
integration package**; projects that do not capture Playwright runs do not need
|
|
17
|
+
it.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add -D @stacknext/playwright @playwright/test
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`@playwright/test >=1.40.0 <2` is an optional peer dependency. The package is
|
|
26
|
+
inert outside an active capture run.
|
|
27
|
+
|
|
28
|
+
## Basic setup
|
|
29
|
+
|
|
30
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
31
|
+
|
|
32
|
+
<!-- coderabbit-ai-generated-section:v1:330156cdeba17c62fdd7205ba9dfb6a1e4eeadd469e4d3cbdc5b72304a6c1817 -->
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// playwright.config.ts
|
|
36
|
+
import { defineConfig } from '@playwright/test'
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
testDir: './e2e',
|
|
40
|
+
workers: 1,
|
|
41
|
+
use: { baseURL: 'http://127.0.0.1:4402' },
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
// e2e/checkout.spec.ts
|
|
49
|
+
import { test, expect } from '@stacknext/playwright'
|
|
50
|
+
|
|
51
|
+
test('checkout completes', async ({ page }) => {
|
|
52
|
+
await page.goto('/checkout')
|
|
53
|
+
await expect(page.getByRole('heading', { name: 'Checkout' })).toBeVisible()
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
58
|
+
|
|
59
|
+
<!-- coderabbit-ai-generated-section:v1:7abbb61d09c1a8f57748d7bf54218ee490f41f98fa4dc39ad4aef8304527a5f6 -->
|
|
60
|
+
|
|
61
|
+
Set `use.baseURL` to your running app’s actual origin (the example app uses
|
|
62
|
+
`http://127.0.0.1:4402`). Run it through the CLI so the capture environment exists:
|
|
63
|
+
|
|
64
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
stacknext capture --name baseline -- \
|
|
68
|
+
pnpm exec playwright test --workers=1 --repeat-each=3
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Running `playwright test` directly does not capture or compare anything.
|
|
72
|
+
|
|
73
|
+
## Exports
|
|
74
|
+
|
|
75
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
76
|
+
|
|
77
|
+
<!-- coderabbit-ai-generated-section:v1:b5db70b760e7288ddbd50c6826a786bb63e51a6bb4cfbf97d44192f11f505f50 -->
|
|
78
|
+
|
|
79
|
+
| Export | Purpose |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `test` | Playwright test with the auto `stacknextCapture` fixture. |
|
|
82
|
+
| `expect` | Re-exported Playwright expect. |
|
|
83
|
+
| `stackNextFixtures` | Exported function returning `{ test, expect }`. |
|
|
84
|
+
| `resolveCaptureConfig` | Reads and validates capture environment variables. |
|
|
85
|
+
| `CaptureTransportError` | Capture configuration/transport error. |
|
|
86
|
+
| `createTraceparent` | Creates a W3C trace context pair. |
|
|
87
|
+
|
|
88
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
89
|
+
|
|
90
|
+
## Documentation map
|
|
91
|
+
|
|
92
|
+
- [Fixture](fixture.md) — annotations, identity and capture lifecycle.
|
|
93
|
+
- [Correlation](correlation.md) — injection, probing and verified samples.
|
|
94
|
+
- [Troubleshooting](troubleshooting.md) — missing samples and incomplete runs.
|
|
95
|
+
|
|
96
|
+
## Related packages
|
|
97
|
+
|
|
98
|
+
- `@stacknext/regression` owns scenario identity and sample schemas.
|
|
99
|
+
- `@stacknext/cli` starts the collector and writes run records.
|
|
100
|
+
- `@stacknext/next` receives the injected trace on the server.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Troubleshooting
|
|
3
|
+
description: Fix missing samples, failed correlation and inactive capture fixtures.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Troubleshooting
|
|
7
|
+
|
|
8
|
+
## The fixture does nothing
|
|
9
|
+
|
|
10
|
+
`resolveCaptureConfig()` returns `null` when capture is inactive. That is normal
|
|
11
|
+
for a direct `playwright test` run. Start the test through:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
stacknext capture --name candidate -- pnpm exec playwright test --workers=1
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## `CaptureTransportError`
|
|
18
|
+
|
|
19
|
+
The run is marked active but the environment is invalid. Check that
|
|
20
|
+
`STACKNEXT_TEST_RUN_ID` matches `run-<16 hex>`,
|
|
21
|
+
`STACKNEXT_COLLECTOR_URL` is a loopback URL and `STACKNEXT_TOKEN` is present.
|
|
22
|
+
Do not set these manually; let `stacknext capture` supply them.
|
|
23
|
+
|
|
24
|
+
## Samples are incomplete
|
|
25
|
+
|
|
26
|
+
1. Confirm the app was started with StackNext instrumentation. The server must
|
|
27
|
+
have an active OTel provider and the W3C propagator.
|
|
28
|
+
2. Check that the browser request URL is loopback or matches `baseURL`.
|
|
29
|
+
3. Look at the sample's correlation reason in `stacknext runs show <run-id>` or
|
|
30
|
+
the MCP `stacknext_get_test_run` response.
|
|
31
|
+
4. Confirm the app received the request before the probe timeout. Increase
|
|
32
|
+
`STACKNEXT_CAPTURE_TIMEOUT_MS` only when the app is genuinely slow to start.
|
|
33
|
+
5. Run with one worker. Parallel workers are not supported for capture.
|
|
34
|
+
|
|
35
|
+
## A scenario has no baseline match
|
|
36
|
+
|
|
37
|
+
The scenario identity changed. Prefer a stable `stacknext.scenario` annotation
|
|
38
|
+
and keep it unchanged between the baseline and candidate. See
|
|
39
|
+
[Fixture](fixture.md).
|
|
40
|
+
|
|
41
|
+
## The test passes but the run exits 3
|
|
42
|
+
|
|
43
|
+
Exit 3 means the child command succeeded but the captured telemetry is
|
|
44
|
+
incomplete. It is not a pass. Inspect the run status and sample correlation
|
|
45
|
+
before comparing.
|
|
46
|
+
|
|
47
|
+
## Timeouts
|
|
48
|
+
|
|
49
|
+
- `STACKNEXT_CAPTURE_SETTLE_MS` (default 500) delays the first probe.
|
|
50
|
+
- `STACKNEXT_CAPTURE_TIMEOUT_MS` (default 5000) bounds probing.
|
|
51
|
+
|
|
52
|
+
Very slow development servers may need a larger timeout, but a consistently
|
|
53
|
+
missing document trace usually indicates broken instrumentation, not a short
|
|
54
|
+
timeout.
|
|
55
|
+
|
|
56
|
+
## Verify
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
stacknext runs list --json
|
|
60
|
+
stacknext runs show <run-id> --json
|
|
61
|
+
stacknext doctor
|
|
62
|
+
```
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacknext/playwright",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Playwright fixtures that correlate browser scenarios with StackNext server telemetry",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"dist"
|
|
8
|
+
"dist",
|
|
9
|
+
"docs"
|
|
9
10
|
],
|
|
10
11
|
"main": "./dist/index.js",
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
"./package.json": "./package.json"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@stacknext/regression": "0.
|
|
22
|
+
"@stacknext/regression": "0.10.0"
|
|
22
23
|
},
|
|
23
24
|
"peerDependencies": {
|
|
24
25
|
"@playwright/test": ">=1.40.0 <2"
|