@parity/product-lab 0.1.1 → 0.1.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +27 -0
  3. package/adapters/browser/playwright/README.md +2 -0
  4. package/adapters/browser/playwright/src/page-frame-capture.js +10 -2
  5. package/adapters/chain/papi/README.md +3 -1
  6. package/adapters/environment/engine/README.md +1 -1
  7. package/adapters/features/cucumber/README.md +4 -0
  8. package/adapters/features/cucumber/src/steps/register-feature-steps.js +15 -1
  9. package/adapters/system/node/README.md +3 -3
  10. package/adapters/video/ffmpeg/README.md +4 -0
  11. package/adapters/video/ffmpeg/src/ffmpeg-video-editor.d.ts +1 -1
  12. package/adapters/video/ffmpeg/src/ffmpeg-video-editor.js +19 -6
  13. package/core/application/README.md +30 -1
  14. package/core/application/src/features/direct-feature-steps.d.ts +23 -0
  15. package/core/application/src/features/direct-feature-steps.js +25 -0
  16. package/core/application/src/features/feature-recording.d.ts +6 -0
  17. package/core/application/src/features/feature-recording.js +3 -0
  18. package/core/application/src/features/feature-scenario.d.ts +10 -8
  19. package/core/application/src/features/feature-scenario.js +11 -15
  20. package/core/application/src/features/feature-step-times.d.ts +11 -1
  21. package/core/application/src/features/feature-step-times.js +20 -6
  22. package/core/application/src/features/lab-feature-session.d.ts +3 -1
  23. package/core/application/src/features/lab-feature-session.js +5 -2
  24. package/core/application/src/features/run-feature-steps.d.ts +3 -1
  25. package/core/application/src/features/run-feature-steps.js +4 -2
  26. package/core/application/src/lab-runtime-use-cases.js +5 -1
  27. package/core/application/src/recordings/demo-markup.d.ts +8 -0
  28. package/core/application/src/recordings/demo-markup.js +11 -1
  29. package/core/application/src/recordings/demo-recording.d.ts +0 -2
  30. package/core/application/src/recordings/demo-recording.js +40 -23
  31. package/core/application/src/recordings/frame-sources.d.ts +20 -1
  32. package/core/application/src/recordings/frame-sources.js +89 -0
  33. package/core/application/src/recordings/record-runs.d.ts +7 -1
  34. package/core/application/src/recordings/record-runs.js +66 -11
  35. package/core/application/src/recordings/recording-draft.d.ts +4 -0
  36. package/core/application/src/recordings/recording-draft.js +13 -4
  37. package/core/domain/README.md +14 -0
  38. package/core/domain/src/recordings/demo-cut.js +6 -4
  39. package/core/domain/src/recordings/demo-holds.d.ts +12 -0
  40. package/core/domain/src/recordings/demo-holds.js +31 -0
  41. package/core/domain/src/recordings/index.d.ts +1 -0
  42. package/core/domain/src/recordings/index.js +1 -0
  43. package/core/domain/src/recordings/recording-data.d.ts +9 -1
  44. package/core/domain/src/recordings/recording-settings.d.ts +5 -1
  45. package/core/domain/src/recordings/recording-settings.js +7 -0
  46. package/core/domain/src/recordings/run-recording.d.ts +2 -0
  47. package/core/domain/src/recordings/run-recording.js +8 -1
  48. package/core/ports/README.md +6 -0
  49. package/core/ports/src/driven/recording/demo-ports.d.ts +2 -0
  50. package/core/ports/src/driven/recording/frame-capture.d.ts +4 -0
  51. package/core/ports/src/driving/demo.d.ts +2 -0
  52. package/core/ports/src/driving/feature-session.d.ts +7 -0
  53. package/entrypoints/cli/README.md +6 -3
  54. package/entrypoints/cli/src/demo-command.d.ts +1 -1
  55. package/entrypoints/cli/src/demo-command.js +10 -5
  56. package/entrypoints/mcp/README.md +3 -0
  57. package/entrypoints/panel/README.md +6 -3
  58. package/entrypoints/panel/src/visible/detached-identities.js +5 -1
  59. package/entrypoints/panel/src/visible/window-frames.js +14 -1
  60. package/package.json +1 -1
@@ -202,3 +202,6 @@ the file. Neither live script is part of the unit suite.
202
202
 
203
203
  The reload test creates its ES-module lab in an OS temporary directory, linking this package's `node_modules`.
204
204
  Concurrent lint can no longer discover a generated lab under the repository's `tests/` without a TypeScript project.
205
+
206
+ Design-resource hashes track the current topic text, including the distinction between passive frames-only
207
+ capture and awaited video capture at feature boundaries.
@@ -417,9 +417,10 @@ Every running actor's app tile has a compact, browser-like address bar in the co
417
417
  (`data-frame`), so a re-created frame never receives an old frame's address. The bar never shows a guessed location.
418
418
 
419
419
  Tests: `node --import tsx --test entrypoints/panel/tests/address-bar.test.ts` (served shell, headless Chromium,
420
- loopback fixture apps on ephemeral ports; a normal tab and the lab window via `openLabWindow`, including real
421
- `framenavigated` reports and the acting guard). Optional `ADDRESS_BAR_SCREENS=<directory>` writes review screenshots
422
- (unset: none).
420
+ loopback fixture apps on ephemeral ports that count browser requests by `Sec-Fetch-Dest`, which Chromium sends
421
+ to these loopback origins, ignoring a local port probe without that header;
422
+ a normal tab and the lab window via `openLabWindow`, including real `framenavigated` reports and the acting guard).
423
+ Optional `ADDRESS_BAR_SCREENS=<directory>` writes review screenshots (unset: none).
423
424
 
424
425
  ## Visible execution: `@product-lab/shell/visible`
425
426
 
@@ -1771,3 +1772,5 @@ Framing reuse (item82): the framing section above retains the original item66 be
1771
1772
  The drawer puts its existing tabs in a full-width row below the title and Close control. Tabs wrap at narrow widths, keeping Recordings reachable without replacing the live app frame. Watch controls the displayed app in a window opened through `openLabWindow`; the server can keep running in the background while that window remains visible.
1772
1773
 
1773
1774
  Opening a recording displays its captured screenshots over the mounted app, with Play/Pause and previous/next screenshot controls. The viewer labels its fixed1.5s image cadence and absence of video; it cannot recover typing or clicks between captures. Back to live restores the app and run controls. Active runs are checked before and after loading the recording, using the latest panel snapshot. The run audit remains available even with zero recorded steps, and incomplete audits explicitly explain that proof is missing.
1775
+
1776
+ Recording captures of tiles and detached windows honor `CaptureOptions.loadComplete` before taking their image and report `loadComplete: true` when checked. Only video feature after-frame checks request this wait; normal captures retain their existing policy. Tests: `tests/window-frames.test.ts` and `tests/detached-identities.test.ts`.
@@ -195,6 +195,10 @@ export function detachedFrameCapture(tiles, detached, options = {}) {
195
195
  const timeoutMs = captureOptions?.timeoutMs ?? options.timeoutMs ?? DETACHED_CAPTURE_TIMEOUT_MS;
196
196
  if (signal?.aborted)
197
197
  throw new Error(`${window.actor.name}'s detached window was not captured: the recorder stopped waiting`);
198
+ if (captureOptions?.loadComplete) {
199
+ await window.app.waitForFunction(() => document.readyState === "complete", undefined, { timeout: timeoutMs });
200
+ signal?.throwIfAborted();
201
+ }
198
202
  const started = Date.now();
199
203
  const unsettled = captureOptions?.settled?.selectors.length ? await settle(window.app, captureOptions.settled) : undefined;
200
204
  if (unsettled)
@@ -211,7 +215,7 @@ export function detachedFrameCapture(tiles, detached, options = {}) {
211
215
  throw new Error(`${window.actor.name}'s detached window gave no frame within ${timeoutMs} ms`, { cause: error });
212
216
  throw new Error(`${window.actor.name}'s detached window could not be captured: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
213
217
  }
214
- return { status: "captured", mediaType: "image/png", bytes: new Uint8Array(bytes), ...settled };
218
+ return { status: "captured", mediaType: "image/png", bytes: new Uint8Array(bytes), ...settled, ...(captureOptions?.loadComplete ? { loadComplete: true } : {}) };
215
219
  },
216
220
  };
217
221
  }
@@ -13,6 +13,19 @@ export function windowFrameCapture(page, frameSelector, media, videos, uiCalls)
13
13
  video: () => windowVideo(page, videos, { source: "lab-window", scope: "window" }),
14
14
  async capture(actorId, options) {
15
15
  const selector = frameSelector(actorId);
16
+ if (options?.loadComplete) {
17
+ const element = await page.locator(selector).elementHandle({ timeout: options.timeoutMs });
18
+ try {
19
+ const app = await element?.contentFrame();
20
+ if (!app)
21
+ return { status: "unavailable", reason: "The displayed app has no current document" };
22
+ await app.waitForLoadState("load", { timeout: options.timeoutMs });
23
+ }
24
+ finally {
25
+ await element?.dispose();
26
+ }
27
+ options.signal?.throwIfAborted();
28
+ }
16
29
  const started = Date.now();
17
30
  const unsettled = options?.settled?.selectors.length ? await settle(page.frameLocator(selector), options.settled) : undefined;
18
31
  if (unsettled)
@@ -45,7 +58,7 @@ export function windowFrameCapture(page, frameSelector, media, videos, uiCalls)
45
58
  const bytes = await cutInWorker(await shot, view.width, { rect: { x, y, width, height } });
46
59
  const after = await page.evaluate(steadyFrameBox, { selector, settleMs: 0 });
47
60
  if (!("moving" in after) && sameBox(after, box))
48
- return { status: "captured", mediaType: "image/png", bytes: new Uint8Array(bytes), ...settled };
61
+ return { status: "captured", mediaType: "image/png", bytes: new Uint8Array(bytes), ...settled, ...(options?.loadComplete ? { loadComplete: true } : {}) };
49
62
  }
50
63
  finally {
51
64
  if (!shot)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parity/product-lab",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "Run and test Polkadot products against real local chains, hosts and browsers: the framework and the product-lab CLI.",
6
6
  "license": "Apache-2.0",