@ingcreators/annot-playwright 0.4.2 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @ingcreators/annot-playwright
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Editable screenshots (`page.screenshot({ annot: { … } })`) now
8
+ stamp schema-2.0 provenance into the XMP packet: the page URL as
9
+ `annot:sourceUrl`, the capture moment as `annot:createdAt`, and
10
+ `annot:producer = "playwright"`.
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+ - Updated dependencies
16
+ - @ingcreators/annot-annotator@0.7.0
17
+ - @ingcreators/annot-core@0.4.0
18
+
3
19
  ## 0.4.2
4
20
 
5
21
  ### Patch Changes
@@ -48,8 +48,12 @@ export declare function playwrightYamlToElementTree(opts: PlaywrightYamlToElemen
48
48
  * resolving its `match: { role, name }` against the live page.
49
49
  */
50
50
  export interface AttachAttributesOptions {
51
- /** Whitelist of HTML attribute names to capture. Same shape as
52
- * `DEFAULT_ATTR_WHITELIST` in `@ingcreators/annot-product-docs`. */
51
+ /** Whitelist of HTML attribute names to capture. Callers should
52
+ * pass the canonical `ELEMENT_TREE_ATTR_WHITELIST` from
53
+ * `@ingcreators/annot-core/element-tree` (which
54
+ * `@ingcreators/annot-product-docs` re-exports as its
55
+ * `DEFAULT_ATTR_WHITELIST`) unless they have a reason to
56
+ * diverge. */
53
57
  whitelist: readonly string[];
54
58
  }
55
59
  /**
package/dist/index.js CHANGED
@@ -255,7 +255,7 @@ function F(e) {
255
255
  let n = e.screenshot;
256
256
  e.screenshot = async function(e = {}) {
257
257
  let t = e?.annot;
258
- return I(t) ? z.call(this, n, e) : n.call(this, e);
258
+ return I(t) ? B.call(this, n, e) : n.call(this, e);
259
259
  }, t[M] = !0;
260
260
  }
261
261
  function I(e) {
@@ -270,7 +270,14 @@ function L(e) {
270
270
  function R(e) {
271
271
  return L(e) ? e.page() : e;
272
272
  }
273
- async function z(e, t) {
273
+ function z(e) {
274
+ try {
275
+ return typeof e.url == "function" ? e.url() : "";
276
+ } catch {
277
+ return "";
278
+ }
279
+ }
280
+ async function B(e, t) {
274
281
  let { annot: n, path: r, ...i } = t, a = i, o = n.editable ?? !0, s = {
275
282
  annot: n,
276
283
  page: R(this),
@@ -278,19 +285,20 @@ async function z(e, t) {
278
285
  }, c = (await Promise.all(N.map((e) => e(s)))).filter((e) => e !== null), l = (n.overlays?.length ?? 0) > 0 || !!n.tags;
279
286
  if (c.length === 0 && !l) return e.call(this, t);
280
287
  for (let e of c) e.prepare && await e.prepare();
281
- let u = await B(this, t.clip), f = await H({
282
- rawBytes: V(await e.call(this, {
288
+ let u = await V(this, t.clip), f = await U({
289
+ rawBytes: H(await e.call(this, {
283
290
  ...a,
284
291
  path: void 0
285
292
  })),
286
293
  annot: n,
287
294
  editable: o,
288
295
  clip: u,
289
- contributions: c
296
+ contributions: c,
297
+ sourceUrl: z(R(this))
290
298
  });
291
299
  return r && await d(r, f), Buffer.from(f);
292
300
  }
293
- async function B(e, t) {
301
+ async function V(e, t) {
294
302
  if (L(e)) {
295
303
  let t = await e.boundingBox();
296
304
  if (!t) throw Error("locator.screenshot({ annot }): locator has no bounding box (probably not visible). Re-test with a stable selector / waitFor().");
@@ -298,11 +306,11 @@ async function B(e, t) {
298
306
  }
299
307
  return t ?? null;
300
308
  }
301
- function V(e) {
309
+ function H(e) {
302
310
  return e instanceof Uint8Array && !(e instanceof Buffer) ? e : new Uint8Array(e.buffer, e.byteOffset, e.byteLength);
303
311
  }
304
- async function H(e) {
305
- let { rawBytes: t, annot: n, editable: r, clip: a, contributions: o } = e, s = K(t), c = [], l = a ? {
312
+ async function U(e) {
313
+ let { rawBytes: t, annot: n, editable: r, clip: a, contributions: o } = e, s = q(t), c = [], l = a ? {
306
314
  width: a.x + a.width,
307
315
  height: a.y + a.height
308
316
  } : s;
@@ -314,11 +322,11 @@ async function H(e) {
314
322
  let u;
315
323
  if (a) {
316
324
  let { kept: e, dropped: t } = g(c, a);
317
- u = e, t.length > 0 && W(t);
325
+ u = e, t.length > 0 && G(t);
318
326
  } else u = c;
319
327
  let d = o.length > 0 || !!n.overlays;
320
328
  if (d && !r) {
321
- let e = U(u), r = `data:image/png;base64,${Buffer.from(t).toString("base64")}`, a = i({ loadSystemFonts: !0 }).toPng({
329
+ let e = W(u), r = `data:image/png;base64,${Buffer.from(t).toString("base64")}`, a = i({ loadSystemFonts: !0 }).toPng({
322
330
  originalDataUrl: r,
323
331
  annotationsSvg: e,
324
332
  width: s.width,
@@ -327,25 +335,28 @@ async function H(e) {
327
335
  return n.tags ? f(a, n.tags) : a;
328
336
  }
329
337
  if (d) {
330
- let e = U(u), r = `data:image/png;base64,${Buffer.from(t).toString("base64")}`;
338
+ let r = W(u), a = `data:image/png;base64,${Buffer.from(t).toString("base64")}`;
331
339
  return i({ loadSystemFonts: !0 }).toEditablePng({
332
- originalDataUrl: r,
333
- annotationsSvg: e,
340
+ originalDataUrl: a,
341
+ annotationsSvg: r,
334
342
  width: s.width,
335
343
  height: s.height,
336
- tags: n.tags
344
+ tags: n.tags,
345
+ sourceUrl: e.sourceUrl,
346
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
347
+ producer: "playwright"
337
348
  });
338
349
  }
339
350
  return n.tags ? f(t, n.tags) : t;
340
351
  }
341
- function U(e) {
352
+ function W(e) {
342
353
  return e.length === 0 ? "<svg xmlns=\"http://www.w3.org/2000/svg\"></svg>" : `<svg xmlns="http://www.w3.org/2000/svg">${r(e)}</svg>`;
343
354
  }
344
- function W(e) {
355
+ function G(e) {
345
356
  let t = e.map(j).join(", "), n = `annot fixture: dropped ${e.length} overlay(s) outside the screenshot clip — ${t}`;
346
- console.warn(n), G(n, e);
357
+ console.warn(n), K(n, e);
347
358
  }
348
- function G(e, t) {
359
+ function K(e, t) {
349
360
  try {
350
361
  let n = l.info?.();
351
362
  if (!n?.annotations) return;
@@ -355,7 +366,7 @@ function G(e, t) {
355
366
  });
356
367
  } catch {}
357
368
  }
358
- function K(e) {
369
+ function q(e) {
359
370
  if (e.length < 24) throw Error("Playwright annot fixture: raw screenshot too short to contain PNG IHDR.");
360
371
  let t = new DataView(e.buffer, e.byteOffset, e.byteLength);
361
372
  return {
@@ -365,20 +376,20 @@ function K(e) {
365
376
  }
366
377
  //#endregion
367
378
  //#region src/fixture.ts
368
- var q = l.extend({
379
+ var J = l.extend({
369
380
  annotator: async ({}, e) => {
370
381
  let t = i();
371
382
  await e({
372
383
  raw: t,
373
- annotateScreenshot: (e, n) => J(t, e, n)
384
+ annotateScreenshot: (e, n) => Y(t, e, n)
374
385
  });
375
386
  },
376
387
  page: async ({ page: e }, t) => {
377
388
  F(Object.getPrototypeOf(e)), F(Object.getPrototypeOf(e.locator("html"))), await t(e);
378
389
  }
379
390
  });
380
- async function J(t, n, i) {
381
- let o = await n.screenshot({ fullPage: i.fullPage }), { width: s, height: c } = Y(o), l = `data:image/png;base64,${o.toString("base64")}`, u = "annotations" in i && i.annotations !== void 0 ? r(i.annotations) : i.annotationsSvg ?? "", d = t.toPng({
391
+ async function Y(t, n, i) {
392
+ let o = await n.screenshot({ fullPage: i.fullPage }), { width: s, height: c } = X(o), l = `data:image/png;base64,${o.toString("base64")}`, u = "annotations" in i && i.annotations !== void 0 ? r(i.annotations) : i.annotationsSvg ?? "", d = t.toPng({
382
393
  originalDataUrl: l,
383
394
  annotationsSvg: u,
384
395
  width: s,
@@ -389,7 +400,7 @@ async function J(t, n, i) {
389
400
  ...i.encode
390
401
  })).bytes;
391
402
  }
392
- function Y(e) {
403
+ function X(e) {
393
404
  if (e.length < 24) throw Error("PNG too short to contain IHDR chunk");
394
405
  let t = new DataView(e.buffer, e.byteOffset, e.byteLength);
395
406
  return {
@@ -398,4 +409,4 @@ function Y(e) {
398
409
  };
399
410
  }
400
411
  //#endregion
401
- export { M as ANNOT_PATCHED, N as annotSourceResolvers, J as annotateScreenshot, t as arrowBetween, m as attachAttributes, n as bboxAnnotationsToSvg, h as captureElementTree, j as describeAnnotation, c as expect, F as patchScreenshot, p as playwrightYamlToElementTree, g as rebaseAnnotations, o as rectForBoundingBox, q as test, s as textAt };
412
+ export { M as ANNOT_PATCHED, N as annotSourceResolvers, Y as annotateScreenshot, t as arrowBetween, m as attachAttributes, n as bboxAnnotationsToSvg, h as captureElementTree, j as describeAnnotation, c as expect, F as patchScreenshot, p as playwrightYamlToElementTree, g as rebaseAnnotations, o as rectForBoundingBox, J as test, s as textAt };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingcreators/annot-playwright",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Playwright fixture for annotated screenshots — emit annotated PNGs from failing tests without leaving the test file. Pairs `test.extend({ annotator })` with the headless renderer from @ingcreators/annot-annotator.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ingcreators",
@@ -44,12 +44,12 @@
44
44
  "devDependencies": {
45
45
  "@playwright/test": "^1.61.1",
46
46
  "typescript": "^6.0.3",
47
- "vite": "^8.0.16",
47
+ "vite": "^8.1.3",
48
48
  "vite-plugin-dts": "^5.0.3"
49
49
  },
50
50
  "dependencies": {
51
- "@ingcreators/annot-annotator": "0.6.0",
52
- "@ingcreators/annot-core": "0.3.1"
51
+ "@ingcreators/annot-annotator": "0.7.0",
52
+ "@ingcreators/annot-core": "0.4.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@playwright/test": "^1.40.0"