@immense/vue-pom-generator 1.0.48 → 1.0.49

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/RELEASE_NOTES.md CHANGED
@@ -1,53 +1,36 @@
1
- # Release Notes: v1.0.48
1
+ I'll gather the release data between v1.0.48 and HEAD to generate accurate release notes.
2
+
3
+ ● Based on the commit data, this is a focused release with one commit. Here are the release notes:
4
+
5
+ ---
2
6
 
3
7
  ## Highlights
4
8
 
5
- - **Split Playwright POM Output**: Added new option to generate split/modular Page Object Models
6
- for improved discoverability and maintainability
7
- - **ts-morph Integration**: Migrated TypeScript code generation to use ts-morph library for more
8
- robust and maintainable type emission
9
- - **Fail-Fast Error Handling**: Now fails immediately when encountering unnameable wrapper
10
- handlers instead of generating invalid code
11
- - **Enhanced Type Safety**: Improved TypeScript code generation structure with dedicated
12
- emitters and better type definitions
9
+ - **Enhanced Playwright visual debugging**: Cursor annotations now render properly during test
10
+ execution
11
+ - Improved test coverage with new Pointer test cases
12
+ - Better visual feedback for automated test runs
13
13
 
14
14
  ## Changes
15
15
 
16
- ### Features
17
- - Add split Playwright POM output for improved discoverability (#12)
18
- - Fail fast on unnameable wrapper handlers instead of silently generating invalid code (#11)
19
-
20
- ### Refactoring & Code Quality
21
- - Migrate to ts-morph for TypeScript code generation
22
- - Structure ts-morph emitters into dedicated modules
23
- - Clean up split stub generation logic
24
- - Address PR feedback on split output implementation
25
- - Remove duplicate rebase leftovers
16
+ ### Fixes
17
+ - **Render Playwright annotations**: Fixed annotation rendering in the visual cursor overlay
18
+ system, ensuring annotation text displays correctly during animated pointer movements
26
19
 
27
- ### Configuration & Types
28
- - Add ts-morph dependency to package.json
29
- - Update plugin types to support split output options
30
- - Enhance manifest generator for split POM structure
20
+ ### Tests
21
+ - Added comprehensive test coverage for Pointer annotation functionality
31
22
 
32
- ### Testing
33
- - Add comprehensive tests for generated TypeScript output
34
- - Add test fixtures for BasePage (full/minimal), Pointer, and playwright-test declarations
35
- - Update class generation coverage tests
36
- - Add option tests for new split output configuration
23
+ ## Breaking Changes
37
24
 
38
- ### Documentation
39
- - Update README with split output documentation and usage examples
25
+ None
40
26
 
41
27
  ## Pull Requests Included
42
28
 
43
- - #12 feat: add split Playwright POM output for discoverability
44
- (https://github.com/immense/vue-pom-generator/pull/12)
45
- - #11 feat: fail fast on unnameable wrapper handlers
46
- (https://github.com/immense/vue-pom-generator/pull/11)
29
+ Based on the commit in this release, this appears to be a direct commit rather than a merged PR
30
+ within the specified time window.
47
31
 
48
32
  ## Testing
49
33
 
50
- Added 173+ lines of new tests for TypeScript code generation, including fixtures for BasePage
51
- and Pointer types. Updated existing test suites to cover split output scenarios and plugin
52
- options.
34
+ - New test cases added to `tests/pointer.test.ts` validating annotation rendering
35
+ - Total test additions: 52 new lines of test code
53
36
 
@@ -5,6 +5,7 @@ import type { PwLocator, PwPage } from "./playwright-types";
5
5
  // ---------------------------------------------------------------------------
6
6
 
7
7
  const __PW_CURSOR_ID__ = "__pw_cursor__";
8
+ const __PW_CURSOR_ANNOTATION_ID__ = "__pw_cursor_annotation__";
8
9
  const __PW_EDITABLE_DESCENDANT_SELECTOR__
9
10
  = "input, textarea, select, [contenteditable=''], [contenteditable='true'], [contenteditable]:not([contenteditable='false'])";
10
11
 
@@ -34,8 +35,9 @@ function __pw_set_cursor_pos__(page: PwPage, x: number, y: number): void {
34
35
 
35
36
  async function __pw_ensure_cursor__(page: PwPage): Promise<void> {
36
37
  const exists = await page.evaluate(
37
- (id: string) => document.getElementById(id) != null,
38
- __PW_CURSOR_ID__,
38
+ ({ cursorId, annotationId }: { cursorId: string; annotationId: string }) =>
39
+ document.getElementById(cursorId) != null && document.getElementById(annotationId) != null,
40
+ { cursorId: __PW_CURSOR_ID__, annotationId: __PW_CURSOR_ANNOTATION_ID__ },
39
41
  );
40
42
  if (exists) return;
41
43
 
@@ -43,7 +45,7 @@ async function __pw_ensure_cursor__(page: PwPage): Promise<void> {
43
45
  __pw_set_cursor_pos__(page, 0, 0);
44
46
 
45
47
  await page.evaluate(
46
- ({ id, src }: { id: string; src: string }) => {
48
+ ({ id, src, annotationId }: { id: string; src: string; annotationId: string }) => {
47
49
  const img = document.createElement("img");
48
50
  img.setAttribute("src", src);
49
51
  img.setAttribute("id", id);
@@ -53,8 +55,32 @@ async function __pw_ensure_cursor__(page: PwPage): Promise<void> {
53
55
  "position:fixed;z-index:2147483647;pointer-events:none;left:0;top:0;transform-origin:0 0;",
54
56
  );
55
57
  document.body.appendChild(img);
58
+
59
+ const annotation = document.createElement("div");
60
+ annotation.setAttribute("id", annotationId);
61
+ annotation.setAttribute(
62
+ "style",
63
+ [
64
+ "position:fixed",
65
+ "z-index:2147483647",
66
+ "pointer-events:none",
67
+ "left:18px",
68
+ "top:18px",
69
+ "max-width:320px",
70
+ "padding:6px 10px",
71
+ "border-radius:999px",
72
+ "background:rgba(15,23,42,0.92)",
73
+ "color:#f8fafc",
74
+ "font:600 13px/1.4 -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
75
+ "box-shadow:0 12px 30px rgba(15,23,42,0.35)",
76
+ "opacity:0",
77
+ "white-space:normal",
78
+ "transform:translate3d(0,0,0)",
79
+ ].join(";"),
80
+ );
81
+ document.body.appendChild(annotation);
56
82
  },
57
- { id: __PW_CURSOR_ID__, src: __PW_CURSOR_PNG__ },
83
+ { id: __PW_CURSOR_ID__, src: __PW_CURSOR_PNG__, annotationId: __PW_CURSOR_ANNOTATION_ID__ },
58
84
  );
59
85
  }
60
86
 
@@ -209,7 +235,7 @@ export class Pointer {
209
235
  target: ElementTarget,
210
236
  executeClick: boolean = true,
211
237
  delayMs: number = 100,
212
- _annotationText: string = "",
238
+ annotationText: string = "",
213
239
  options?: {
214
240
  afterClick?: AfterPointerClick;
215
241
  },
@@ -248,6 +274,7 @@ export class Pointer {
248
274
  const clickDelayMs = opts.pointer?.clickDelayMilliseconds ?? 0;
249
275
  const extraDelayMs = Math.max(0, opts.extraDelayMs ?? 0);
250
276
  const actionDelayMs = Math.max(0, delayMs);
277
+ const trimmedAnnotationText = annotationText.trim();
251
278
 
252
279
  // Inject the visual cursor if it doesn't exist yet.
253
280
  await __pw_ensure_cursor__(this.page);
@@ -263,22 +290,47 @@ export class Pointer {
263
290
  if (moveDurationMs > 0 && distance > 0) {
264
291
  // Glide the cursor image using a CSS transition.
265
292
  await this.page.evaluate(
266
- ({ id, sx, sy, ex, ey, dur, style }: {
267
- id: string; sx: number; sy: number; ex: number; ey: number; dur: number; style: string;
293
+ ({ id, annotationId, sx, sy, ex, ey, dur, style, annotationText }: {
294
+ id: string; annotationId: string; sx: number; sy: number; ex: number; ey: number; dur: number; style: string; annotationText: string;
268
295
  }) => {
269
296
  const el = document.getElementById(id);
297
+ const annotation = document.getElementById(annotationId);
270
298
  if (!el) return;
271
299
  el.style.transition = "";
272
300
  el.style.willChange = "left, top";
273
301
  el.style.left = `${sx}px`;
274
302
  el.style.top = `${sy}px`;
303
+ if (annotation) {
304
+ annotation.textContent = annotationText;
305
+ annotation.style.transition = "";
306
+ annotation.style.willChange = "left, top, opacity";
307
+ annotation.style.left = `${sx + 18}px`;
308
+ annotation.style.top = `${sy + 22}px`;
309
+ annotation.style.opacity = annotationText ? "1" : "0";
310
+ }
275
311
  // Force reflow so the browser registers the start position before transitioning.
276
312
  void el.offsetWidth;
313
+ void annotation?.offsetWidth;
277
314
  el.style.transition = `left ${dur}ms ${style}, top ${dur}ms ${style}`;
278
315
  el.style.left = `${ex}px`;
279
316
  el.style.top = `${ey}px`;
317
+ if (annotation) {
318
+ annotation.style.transition = `left ${dur}ms ${style}, top ${dur}ms ${style}, opacity 120ms ease-in-out`;
319
+ annotation.style.left = `${ex + 18}px`;
320
+ annotation.style.top = `${ey + 22}px`;
321
+ }
322
+ },
323
+ {
324
+ id: __PW_CURSOR_ID__,
325
+ annotationId: __PW_CURSOR_ANNOTATION_ID__,
326
+ sx: startX,
327
+ sy: startY,
328
+ ex: endX,
329
+ ey: endY,
330
+ dur: moveDurationMs,
331
+ style: transitionStyle,
332
+ annotationText: trimmedAnnotationText,
280
333
  },
281
- { id: __PW_CURSOR_ID__, sx: startX, sy: startY, ex: endX, ey: endY, dur: moveDurationMs, style: transitionStyle },
282
334
  );
283
335
  // Wait for the animation to finish.
284
336
  await this.page.waitForTimeout(moveDurationMs + 25);
@@ -286,11 +338,18 @@ export class Pointer {
286
338
  else {
287
339
  // Teleport (distance 0 or duration 0).
288
340
  await this.page.evaluate(
289
- ({ id, x, y }: { id: string; x: number; y: number }) => {
341
+ ({ id, annotationId, x, y, annotationText }: { id: string; annotationId: string; x: number; y: number; annotationText: string }) => {
290
342
  const el = document.getElementById(id);
291
343
  if (el) { el.style.left = `${x}px`; el.style.top = `${y}px`; }
344
+ const annotation = document.getElementById(annotationId);
345
+ if (annotation) {
346
+ annotation.textContent = annotationText;
347
+ annotation.style.left = `${x + 18}px`;
348
+ annotation.style.top = `${y + 22}px`;
349
+ annotation.style.opacity = annotationText ? "1" : "0";
350
+ }
292
351
  },
293
- { id: __PW_CURSOR_ID__, x: endX, y: endY },
352
+ { id: __PW_CURSOR_ID__, annotationId: __PW_CURSOR_ANNOTATION_ID__, x: endX, y: endY, annotationText: trimmedAnnotationText },
294
353
  );
295
354
  }
296
355
 
@@ -58,7 +58,7 @@ export declare class Pointer {
58
58
  private getTestId;
59
59
  private isEditableElement;
60
60
  private resolveEditableLocator;
61
- animateCursorToElement(target: ElementTarget, executeClick?: boolean, delayMs?: number, _annotationText?: string, options?: {
61
+ animateCursorToElement(target: ElementTarget, executeClick?: boolean, delayMs?: number, annotationText?: string, options?: {
62
62
  afterClick?: AfterPointerClick;
63
63
  }): Promise<void>;
64
64
  animateCursorToElementAndClickAndFill(target: ElementTarget, text: string, executeClick?: boolean, delayMs?: number, annotationText?: string, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"Pointer.d.ts","sourceRoot":"","sources":["../../class-generation/Pointer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAgE5D,MAAM,WAAW,0BAA0B;IAC1C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,sDAAsD;IACtD,OAAO,CAAC,EAAE;QACT;;;;WAIG;QACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAE9B;;;WAGG;QACH,eAAe,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;QAE7E;;;WAGG;QACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;IAEF,uCAAuC;IACvC,QAAQ,CAAC,EAAE;QACV;;;WAGG;QACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;CACF;AASD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAavF;AAED,MAAM,WAAW,qBAAqB;IACrC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtF,KAAK,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAMxC,qBAAa,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAEtB,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;IAKxD,OAAO,CAAC,SAAS;YAIH,SAAS;YAMT,iBAAiB;YAmBjB,sBAAsB;IAmBvB,sBAAsB,CAClC,MAAM,EAAE,aAAa,EACrB,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,MAAY,EACrB,eAAe,GAAE,MAAW,EAC5B,OAAO,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAC/B,GACC,OAAO,CAAC,IAAI,CAAC;IAsHH,qCAAqC,CACjD,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,MAAY,EACrB,cAAc,GAAE,MAAW,EAC3B,OAAO,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAC/B,GACC,OAAO,CAAC,IAAI,CAAC;CAiBhB"}
1
+ {"version":3,"file":"Pointer.d.ts","sourceRoot":"","sources":["../../class-generation/Pointer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA0F5D,MAAM,WAAW,0BAA0B;IAC1C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,sDAAsD;IACtD,OAAO,CAAC,EAAE;QACT;;;;WAIG;QACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAE9B;;;WAGG;QACH,eAAe,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;QAE7E;;;WAGG;QACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;IAEF,uCAAuC;IACvC,QAAQ,CAAC,EAAE;QACV;;;WAGG;QACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;CACF;AASD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAavF;AAED,MAAM,WAAW,qBAAqB;IACrC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtF,KAAK,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAMxC,qBAAa,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAEtB,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM;IAKxD,OAAO,CAAC,SAAS;YAIH,SAAS;YAMT,iBAAiB;YAmBjB,sBAAsB;IAmBvB,sBAAsB,CAClC,MAAM,EAAE,aAAa,EACrB,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,MAAY,EACrB,cAAc,GAAE,MAAW,EAC3B,OAAO,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAC/B,GACC,OAAO,CAAC,IAAI,CAAC;IAuJH,qCAAqC,CACjD,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,MAAY,EACrB,cAAc,GAAE,MAAW,EAC3B,OAAO,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAC/B,GACC,OAAO,CAAC,IAAI,CAAC;CAiBhB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immense/vue-pom-generator",
3
- "version": "1.0.48",
3
+ "version": "1.0.49",
4
4
  "description": "Injects data-testid attributes for all interactive elements and generates page object models for every page.",
5
5
  "type": "module",
6
6
  "repository": {