@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
|
-
●
|
|
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
|
-
- **
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
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
|
-
###
|
|
17
|
-
-
|
|
18
|
-
|
|
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
|
-
###
|
|
28
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
39
|
-
- Update README with split output documentation and usage examples
|
|
25
|
+
None
|
|
40
26
|
|
|
41
27
|
## Pull Requests Included
|
|
42
28
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
(
|
|
38
|
-
|
|
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
|
-
|
|
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,
|
|
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;
|
|
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