@immense/vue-pom-generator 1.0.48 → 1.0.50

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 (37) hide show
  1. package/RELEASE_NOTES.md +47 -36
  2. package/class-generation/{BasePage.ts → base-page.ts} +19 -4
  3. package/class-generation/callout.ts +827 -0
  4. package/class-generation/floating-ui.ts +814 -0
  5. package/class-generation/index.ts +11 -10
  6. package/class-generation/{Pointer.ts → pointer.ts} +81 -42
  7. package/dist/class-generation/{BasePage.d.ts → base-page.d.ts} +6 -2
  8. package/dist/class-generation/base-page.d.ts.map +1 -0
  9. package/dist/class-generation/callout.d.ts +20 -0
  10. package/dist/class-generation/callout.d.ts.map +1 -0
  11. package/dist/class-generation/floating-ui.d.ts +100 -0
  12. package/dist/class-generation/floating-ui.d.ts.map +1 -0
  13. package/dist/class-generation/{Pointer.d.ts → pointer.d.ts} +6 -6
  14. package/dist/class-generation/pointer.d.ts.map +1 -0
  15. package/dist/index.cjs +27 -14
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.mjs +27 -14
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/playwright.config.d.ts +3 -0
  20. package/dist/playwright.config.d.ts.map +1 -0
  21. package/dist/plugin/support/build-plugin.d.ts.map +1 -1
  22. package/dist/plugin/support/dev-plugin.d.ts.map +1 -1
  23. package/dist/plugin/types.d.ts +1 -1
  24. package/dist/tests/fixtures/generated-tsc/{BasePage.full.d.ts → base-page.full.d.ts} +1 -1
  25. package/dist/tests/fixtures/generated-tsc/base-page.full.d.ts.map +1 -0
  26. package/dist/tests/fixtures/generated-tsc/{BasePage.minimal.d.ts → base-page.minimal.d.ts} +1 -1
  27. package/dist/tests/fixtures/generated-tsc/base-page.minimal.d.ts.map +1 -0
  28. package/dist/tests/fixtures/generated-tsc/{Pointer.d.ts → pointer.d.ts} +1 -1
  29. package/dist/tests/fixtures/generated-tsc/pointer.d.ts.map +1 -0
  30. package/dist/tests/playwright/pointer-callout.spec.d.ts +2 -0
  31. package/dist/tests/playwright/pointer-callout.spec.d.ts.map +1 -0
  32. package/package.json +6 -2
  33. package/dist/class-generation/BasePage.d.ts.map +0 -1
  34. package/dist/class-generation/Pointer.d.ts.map +0 -1
  35. package/dist/tests/fixtures/generated-tsc/BasePage.full.d.ts.map +0 -1
  36. package/dist/tests/fixtures/generated-tsc/BasePage.minimal.d.ts.map +0 -1
  37. package/dist/tests/fixtures/generated-tsc/Pointer.d.ts.map +0 -1
@@ -45,7 +45,7 @@ import {
45
45
 
46
46
  // Intentionally imported so tooling understands this exported helper is part of the
47
47
  // generated POM public surface (it is consumed by generated Playwright fixtures).
48
- import { setPlaywrightAnimationOptions } from "./Pointer";
48
+ import { setPlaywrightAnimationOptions } from "./pointer";
49
49
 
50
50
  void setPlaywrightAnimationOptions;
51
51
 
@@ -919,7 +919,7 @@ async function generateSplitTypeScriptFiles(
919
919
  customPomImportNameCollisionBehavior: options.customPomImportNameCollisionBehavior,
920
920
  });
921
921
 
922
- const runtimeBasePagePath = path.join(base, "_pom-runtime", "class-generation", "BasePage.ts");
922
+ const runtimeBasePagePath = path.join(base, "_pom-runtime", "class-generation", "base-page.ts");
923
923
  const files: GeneratedFileOutput[] = [];
924
924
 
925
925
  for (const [name, deps] of entries) {
@@ -2385,7 +2385,7 @@ function getRuntimeGeneratedAssetSpecs(baseDir: string, basePageClassPath: strin
2385
2385
  const runtimeClassGenSourceDir = resolvePluginAsset("../class-generation");
2386
2386
  const runtimeClassGenFiles = fs.readdirSync(runtimeClassGenSourceDir)
2387
2387
  .filter(file => file.endsWith(".ts"))
2388
- .filter(file => file !== "BasePage.ts" && file !== "index.ts")
2388
+ .filter(file => file !== "base-page.ts" && file !== "index.ts")
2389
2389
  .sort((left, right) => left.localeCompare(right));
2390
2390
 
2391
2391
  return [
@@ -2401,8 +2401,8 @@ function getRuntimeGeneratedAssetSpecs(baseDir: string, basePageClassPath: strin
2401
2401
  })),
2402
2402
  {
2403
2403
  absolutePath: basePageClassPath,
2404
- description: "BasePage.ts",
2405
- outputPath: path.join(runtimeClassGenAbs, "BasePage.ts"),
2404
+ description: "base-page.ts",
2405
+ outputPath: path.join(runtimeClassGenAbs, "base-page.ts"),
2406
2406
  },
2407
2407
  ];
2408
2408
  }
@@ -2643,7 +2643,7 @@ async function generateAggregatedFiles(
2643
2643
  }
2644
2644
 
2645
2645
  // Aggregate mode goal: consolidate all generated POM classes into one file.
2646
- // Instead of inlining BasePage/Pointer helpers and stripping imports via regex, we
2646
+ // Instead of inlining BasePage/Pointer/Callout helpers and stripping imports via regex, we
2647
2647
  // emit/copy those dependencies into the output folder and import them normally.
2648
2648
  //
2649
2649
  // This keeps output deterministic and avoids fragile source rewriting.
@@ -2651,12 +2651,13 @@ async function generateAggregatedFiles(
2651
2651
  const runtimeClassGenRel = `${runtimeDirRel}/class-generation`;
2652
2652
 
2653
2653
  imports.push(`import type { PwLocator, PwPage } from "${runtimeClassGenRel}/playwright-types";`);
2654
- imports.push(`import { BasePage } from "${runtimeClassGenRel}/BasePage";`);
2655
- imports.push(`import type { Fluent } from "${runtimeClassGenRel}/BasePage";`);
2654
+ imports.push(`import { BasePage } from "${runtimeClassGenRel}/base-page";`);
2655
+ imports.push(`import type { Fluent } from "${runtimeClassGenRel}/base-page";`);
2656
2656
  imports.push(`export * from "${runtimeDirRel}/click-instrumentation";`);
2657
2657
  imports.push(`export * from "${runtimeClassGenRel}/playwright-types";`);
2658
- imports.push(`export * from "${runtimeClassGenRel}/Pointer";`);
2659
- imports.push(`export * from "${runtimeClassGenRel}/BasePage";`);
2658
+ imports.push(`export * from "${runtimeClassGenRel}/callout";`);
2659
+ imports.push(`export * from "${runtimeClassGenRel}/pointer";`);
2660
+ imports.push(`export * from "${runtimeClassGenRel}/base-page";`);
2660
2661
 
2661
2662
  const customPomImportResolution = resolveCustomPomImportResolution(generatedClassNames, projectRoot, {
2662
2663
  customPomDir: options.customPomDir,
@@ -1,9 +1,6 @@
1
+ import { Callout, type ElementTarget } from "./callout";
1
2
  import type { PwLocator, PwPage } from "./playwright-types";
2
3
 
3
- // ---------------------------------------------------------------------------
4
- // Cursor visual overlay helpers
5
- // ---------------------------------------------------------------------------
6
-
7
4
  const __PW_CURSOR_ID__ = "__pw_cursor__";
8
5
  const __PW_EDITABLE_DESCENDANT_SELECTOR__
9
6
  = "input, textarea, select, [contenteditable=''], [contenteditable='true'], [contenteditable]:not([contenteditable='false'])";
@@ -21,7 +18,6 @@ const __PW_CURSOR_PNG__ =
21
18
  + "ONcpr3PrXy9VfS473M/D7H+TLmrqsXtOGctvxvMv2oVNP+Av0uHbzbxyJaywyUjx8TlnPY2YxqkD"
22
19
  + "dAAAAABJRU5ErkJggg==";
23
20
 
24
- // Per-page cursor position (viewport coords). WeakMap so pages can be GC'd.
25
21
  const __pw_cursor_positions__ = new WeakMap<object, { x: number; y: number }>();
26
22
 
27
23
  function __pw_get_cursor_pos__(page: PwPage): { x: number; y: number } {
@@ -34,12 +30,11 @@ function __pw_set_cursor_pos__(page: PwPage, x: number, y: number): void {
34
30
 
35
31
  async function __pw_ensure_cursor__(page: PwPage): Promise<void> {
36
32
  const exists = await page.evaluate(
37
- (id: string) => document.getElementById(id) != null,
38
- __PW_CURSOR_ID__,
33
+ ({ cursorId }: { cursorId: string }) => document.getElementById(cursorId) != null,
34
+ { cursorId: __PW_CURSOR_ID__ },
39
35
  );
40
36
  if (exists) return;
41
37
 
42
- // Reset tracked position for this page.
43
38
  __pw_set_cursor_pos__(page, 0, 0);
44
39
 
45
40
  await page.evaluate(
@@ -47,14 +42,16 @@ async function __pw_ensure_cursor__(page: PwPage): Promise<void> {
47
42
  const img = document.createElement("img");
48
43
  img.setAttribute("src", src);
49
44
  img.setAttribute("id", id);
50
- // position:fixed keeps coordinates viewport-relative (matching Playwright boundingBox).
51
45
  img.setAttribute(
52
46
  "style",
53
47
  "position:fixed;z-index:2147483647;pointer-events:none;left:0;top:0;transform-origin:0 0;",
54
48
  );
55
49
  document.body.appendChild(img);
56
50
  },
57
- { id: __PW_CURSOR_ID__, src: __PW_CURSOR_PNG__ },
51
+ {
52
+ id: __PW_CURSOR_ID__,
53
+ src: __PW_CURSOR_PNG__,
54
+ },
58
55
  );
59
56
  }
60
57
 
@@ -142,8 +139,6 @@ export interface AfterPointerClickInfo {
142
139
 
143
140
  export type AfterPointerClick = (info: AfterPointerClickInfo) => void | Promise<void>;
144
141
 
145
- type ElementTarget = string | PwLocator;
146
-
147
142
  // ---------------------------------------------------------------------------
148
143
  // Pointer class
149
144
  // ---------------------------------------------------------------------------
@@ -151,10 +146,12 @@ type ElementTarget = string | PwLocator;
151
146
  export class Pointer {
152
147
  private readonly page: PwPage;
153
148
  private readonly testIdAttribute: string;
149
+ private readonly callout: Callout;
154
150
 
155
- public constructor(page: PwPage, testIdAttribute: string) {
151
+ public constructor(page: PwPage, testIdAttribute: string, callout?: Callout) {
156
152
  this.page = page;
157
153
  this.testIdAttribute = (testIdAttribute ?? "data-testid").trim() || "data-testid";
154
+ this.callout = callout ?? new Callout(page);
158
155
  }
159
156
 
160
157
  private toLocator(target: ElementTarget): PwLocator {
@@ -208,13 +205,14 @@ export class Pointer {
208
205
  public async animateCursorToElement(
209
206
  target: ElementTarget,
210
207
  executeClick: boolean = true,
211
- delayMs: number = 100,
212
- _annotationText: string = "",
208
+ delayMs: number = 1000,
209
+ annotationText: string = "",
213
210
  options?: {
214
211
  afterClick?: AfterPointerClick;
215
212
  },
216
213
  ): Promise<void> {
217
214
  const locator = this.toLocator(target);
215
+ const trimmedAnnotationText = annotationText.trim();
218
216
 
219
217
  try {
220
218
  await locator.first().scrollIntoViewIfNeeded();
@@ -227,6 +225,13 @@ export class Pointer {
227
225
  const animEnabled = opts.enabled !== false;
228
226
 
229
227
  if (!animEnabled) {
228
+ if (trimmedAnnotationText) {
229
+ await this.callout.showForElement(locator, trimmedAnnotationText);
230
+ }
231
+ else {
232
+ await this.callout.hide();
233
+ }
234
+
230
235
  // Fast path: no animations.
231
236
  const extraDelay = Math.max(0, opts.extraDelayMs ?? 0);
232
237
  if (extraDelay > 0) await this.page.waitForTimeout(extraDelay);
@@ -260,42 +265,76 @@ export class Pointer {
260
265
  const { x: startX, y: startY } = __pw_get_cursor_pos__(this.page);
261
266
  const distance = Math.sqrt((endX - startX) ** 2 + (endY - startY) ** 2);
262
267
 
263
- if (moveDurationMs > 0 && distance > 0) {
264
- // Glide the cursor image using a CSS transition.
265
- 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;
268
- }) => {
269
- const el = document.getElementById(id);
270
- if (!el) return;
271
- el.style.transition = "";
272
- el.style.willChange = "left, top";
273
- el.style.left = `${sx}px`;
274
- el.style.top = `${sy}px`;
275
- // Force reflow so the browser registers the start position before transitioning.
268
+ const shouldAnimate = moveDurationMs > 0 && distance > 0;
269
+ await this.page.evaluate(
270
+ ({
271
+ dur,
272
+ ex,
273
+ ey,
274
+ id,
275
+ style,
276
+ sx,
277
+ sy,
278
+ animate,
279
+ }: {
280
+ dur: number;
281
+ ex: number;
282
+ ey: number;
283
+ id: string;
284
+ style: string;
285
+ sx: number;
286
+ sy: number;
287
+ animate: boolean;
288
+ }) => {
289
+ const el = document.getElementById(id);
290
+ if (!el) {
291
+ return;
292
+ }
293
+
294
+ el.style.transition = "";
295
+ el.style.willChange = "left, top";
296
+ el.style.left = `${animate ? sx : ex}px`;
297
+ el.style.top = `${animate ? sy : ey}px`;
298
+
299
+ if (animate) {
276
300
  void el.offsetWidth;
277
301
  el.style.transition = `left ${dur}ms ${style}, top ${dur}ms ${style}`;
278
302
  el.style.left = `${ex}px`;
279
303
  el.style.top = `${ey}px`;
280
- },
281
- { id: __PW_CURSOR_ID__, sx: startX, sy: startY, ex: endX, ey: endY, dur: moveDurationMs, style: transitionStyle },
282
- );
283
- // Wait for the animation to finish.
284
- await this.page.waitForTimeout(moveDurationMs + 25);
304
+ }
305
+ },
306
+ {
307
+ dur: moveDurationMs,
308
+ ex: endX,
309
+ ey: endY,
310
+ id: __PW_CURSOR_ID__,
311
+ style: transitionStyle,
312
+ sx: startX,
313
+ sy: startY,
314
+ animate: shouldAnimate,
315
+ },
316
+ );
317
+
318
+ if (trimmedAnnotationText) {
319
+ await this.callout.showForElement(locator, trimmedAnnotationText, {
320
+ skipScroll: true,
321
+ targetBox: box,
322
+ });
285
323
  }
286
324
  else {
287
- // Teleport (distance 0 or duration 0).
288
- await this.page.evaluate(
289
- ({ id, x, y }: { id: string; x: number; y: number }) => {
290
- const el = document.getElementById(id);
291
- if (el) { el.style.left = `${x}px`; el.style.top = `${y}px`; }
292
- },
293
- { id: __PW_CURSOR_ID__, x: endX, y: endY },
294
- );
325
+ await this.callout.hide();
326
+ }
327
+
328
+ if (shouldAnimate) {
329
+ // Wait for the animation to finish.
330
+ await this.page.waitForTimeout(moveDurationMs + 25);
295
331
  }
296
332
 
297
333
  __pw_set_cursor_pos__(this.page, endX, endY);
298
334
  }
335
+ else {
336
+ await this.callout.hide();
337
+ }
299
338
 
300
339
  // Apply action delay + extra delay.
301
340
  const totalDelay = actionDelayMs + extraDelayMs;
@@ -335,7 +374,7 @@ export class Pointer {
335
374
  target: ElementTarget,
336
375
  text: string,
337
376
  executeClick: boolean = true,
338
- delayMs: number = 100,
377
+ delayMs: number = 1000,
339
378
  annotationText: string = "",
340
379
  options?: {
341
380
  afterClick?: AfterPointerClick;
@@ -1,5 +1,5 @@
1
1
  import type { PwLocator, PwPage } from "./playwright-types";
2
- import type { AfterPointerClick } from "./Pointer";
2
+ import type { AfterPointerClick } from "./pointer";
3
3
  /**
4
4
  * A chainable, thenable wrapper around a page object.
5
5
  *
@@ -35,6 +35,7 @@ export declare class ObjectId {
35
35
  export declare class BasePage {
36
36
  protected page: PwPage;
37
37
  protected readonly testIdAttribute: string;
38
+ private readonly callout;
38
39
  private readonly pointer;
39
40
  /**
40
41
  * @param {Page} page - Playwright page object
@@ -54,6 +55,9 @@ export declare class BasePage {
54
55
  protected animateCursorToElement(target: string | PwLocator, executeClick?: boolean, delayMs?: number, annotationText?: string, options?: {
55
56
  afterClick?: AfterPointerClick;
56
57
  }): Promise<void>;
58
+ showCallout(target: string | PwLocator, annotationText: string): Promise<void>;
59
+ showCalloutByTestId(testId: string, annotationText: string): Promise<void>;
60
+ hideCallout(): Promise<void>;
57
61
  /**
58
62
  * Creates an indexable proxy for keyed elements so generated POMs can expose
59
63
  * ergonomic accessors like:
@@ -133,4 +137,4 @@ export declare class BasePage {
133
137
  protected selectByTestId(testId: string, value: string): Promise<void>;
134
138
  }
135
139
  export {};
136
- //# sourceMappingURL=BasePage.d.ts.map
140
+ //# sourceMappingURL=base-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-page.d.ts","sourceRoot":"","sources":["../../class-generation/base-page.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { PwLocator, PwPage } from "./playwright-types";
2
+ export type ElementTarget = string | PwLocator;
3
+ export interface CalloutTargetBox {
4
+ x: number;
5
+ y: number;
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export interface ShowCalloutOptions {
10
+ skipScroll?: boolean;
11
+ targetBox?: CalloutTargetBox;
12
+ }
13
+ export declare class Callout {
14
+ private readonly page;
15
+ constructor(page: PwPage);
16
+ private toLocator;
17
+ hide(): Promise<void>;
18
+ showForElement(target: ElementTarget, annotationText: string, options?: ShowCalloutOptions): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=callout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callout.d.ts","sourceRoot":"","sources":["../../class-generation/callout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAiE5D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAsBD,MAAM,WAAW,kBAAkB;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AA0ZD,qBAAa,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAEX,IAAI,EAAE,MAAM;IAI/B,OAAO,CAAC,SAAS;IAIJ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAkCrB,cAAc,CAC1B,MAAM,EAAE,aAAa,EACrB,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;CA6QhB"}
@@ -0,0 +1,100 @@
1
+ declare function detectOverflow(state: any, options: any): Promise<{
2
+ top: number;
3
+ bottom: number;
4
+ left: number;
5
+ right: number;
6
+ }>;
7
+ declare var computePosition: (reference: any, floating: any, config: any) => Promise<{
8
+ x: any;
9
+ y: any;
10
+ placement: any;
11
+ strategy: any;
12
+ middlewareData: {};
13
+ }>;
14
+ declare var arrow: (options: any) => {
15
+ name: string;
16
+ options: any;
17
+ fn(state: any): Promise<{
18
+ data?: undefined;
19
+ reset?: undefined;
20
+ } | {
21
+ [x: string]: any;
22
+ data: {
23
+ alignmentOffset?: number | undefined;
24
+ centerOffset: number;
25
+ };
26
+ reset: boolean;
27
+ }>;
28
+ };
29
+ declare var autoPlacement: (options: any) => {
30
+ name: string;
31
+ options: any;
32
+ fn(state: any): Promise<{
33
+ reset?: undefined;
34
+ data?: undefined;
35
+ } | {
36
+ reset: {
37
+ placement: any;
38
+ };
39
+ data?: undefined;
40
+ } | {
41
+ data: {
42
+ index: any;
43
+ overflows: any[];
44
+ };
45
+ reset: {
46
+ placement: any;
47
+ };
48
+ }>;
49
+ };
50
+ declare var flip: (options: any) => {
51
+ name: string;
52
+ options: any;
53
+ fn(state: any): Promise<{
54
+ data?: undefined;
55
+ reset?: undefined;
56
+ } | {
57
+ data: {
58
+ index: any;
59
+ overflows: any;
60
+ };
61
+ reset: {
62
+ placement: any;
63
+ };
64
+ } | {
65
+ reset: {
66
+ placement: any;
67
+ };
68
+ data?: undefined;
69
+ }>;
70
+ };
71
+ declare var offset: (options: any) => {
72
+ name: string;
73
+ options: any;
74
+ fn(state: any): Promise<{
75
+ x?: undefined;
76
+ y?: undefined;
77
+ data?: undefined;
78
+ } | {
79
+ x: any;
80
+ y: any;
81
+ data: {
82
+ placement: any;
83
+ x: number;
84
+ y: number;
85
+ };
86
+ }>;
87
+ };
88
+ declare var shift: (options: any) => {
89
+ name: string;
90
+ options: any;
91
+ fn(state: any): Promise<any>;
92
+ };
93
+ declare var limitShift: (options: any) => {
94
+ options: any;
95
+ fn(state: any): {
96
+ [x: string]: any;
97
+ };
98
+ };
99
+ export { arrow, autoPlacement, computePosition, detectOverflow, flip, limitShift, offset, shift };
100
+ //# sourceMappingURL=floating-ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"floating-ui.d.ts","sourceRoot":"","sources":["../../class-generation/floating-ui.ts"],"names":[],"mappings":"AA2LA,iBAAe,cAAc,CAAC,KAAK,KAAA,EAAE,OAAO,KAAA;;;;;GAuD3C;AAED,QAAA,IAAI,eAAe,GAAU,cAAS,EAAE,aAAQ,EAAE,WAAM;;;;;;EAsFvD,CAAC;AACF,QAAA,IAAI,KAAK,GAAI,YAAO;;;;;;;;;;;;;;CA6DlB,CAAC;AAUH,QAAA,IAAI,aAAa,GAAY,YAAO;;;;;;;;;;;;;;;;;;;;CAsFnC,CAAC;AACF,QAAA,IAAI,IAAI,GAAY,YAAO;;;;;;;;;;;;;;;;;;;;CA4G1B,CAAC;AAuCF,QAAA,IAAI,MAAM,GAAY,YAAO;;;;;;;;;;;;;;;;CA6B5B,CAAC;AACF,QAAA,IAAI,KAAK,GAAY,YAAO;;;;CAwE3B,CAAC;AACF,QAAA,IAAI,UAAU,GAAY,YAAO;;;;;CAgEhC,CAAC;AACF,OAAO,EACL,KAAK,EACL,aAAa,EACb,eAAe,EACf,cAAc,EACd,IAAI,EACJ,UAAU,EACV,MAAM,EACN,KAAK,EACN,CAAC"}
@@ -1,4 +1,5 @@
1
- import type { PwLocator, PwPage } from "./playwright-types";
1
+ import { Callout, type ElementTarget } from "./callout";
2
+ import type { PwPage } from "./playwright-types";
2
3
  export interface PlaywrightAnimationOptions {
3
4
  /**
4
5
  * Set to false to disable all animations and delays. Clicks/fills still happen.
@@ -49,21 +50,20 @@ export interface AfterPointerClickInfo {
49
50
  instrumented: boolean;
50
51
  }
51
52
  export type AfterPointerClick = (info: AfterPointerClickInfo) => void | Promise<void>;
52
- type ElementTarget = string | PwLocator;
53
53
  export declare class Pointer {
54
54
  private readonly page;
55
55
  private readonly testIdAttribute;
56
- constructor(page: PwPage, testIdAttribute: string);
56
+ private readonly callout;
57
+ constructor(page: PwPage, testIdAttribute: string, callout?: Callout);
57
58
  private toLocator;
58
59
  private getTestId;
59
60
  private isEditableElement;
60
61
  private resolveEditableLocator;
61
- animateCursorToElement(target: ElementTarget, executeClick?: boolean, delayMs?: number, _annotationText?: string, options?: {
62
+ animateCursorToElement(target: ElementTarget, executeClick?: boolean, delayMs?: number, annotationText?: string, options?: {
62
63
  afterClick?: AfterPointerClick;
63
64
  }): Promise<void>;
64
65
  animateCursorToElementAndClickAndFill(target: ElementTarget, text: string, executeClick?: boolean, delayMs?: number, annotationText?: string, options?: {
65
66
  afterClick?: AfterPointerClick;
66
67
  }): Promise<void>;
67
68
  }
68
- export {};
69
- //# sourceMappingURL=Pointer.d.ts.map
69
+ //# sourceMappingURL=pointer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointer.d.ts","sourceRoot":"","sources":["../../class-generation/pointer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAa,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA4D5D,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;AAMtF,qBAAa,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEf,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAM3E,OAAO,CAAC,SAAS;YAIH,SAAS;YAMT,iBAAiB;YAmBjB,sBAAsB;IAmBvB,sBAAsB,CAClC,MAAM,EAAE,aAAa,EACrB,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,MAAa,EACtB,cAAc,GAAE,MAAW,EAC3B,OAAO,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAC/B,GACC,OAAO,CAAC,IAAI,CAAC;IAgKH,qCAAqC,CACjD,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,OAAc,EAC5B,OAAO,GAAE,MAAa,EACtB,cAAc,GAAE,MAAW,EAC3B,OAAO,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,iBAAiB,CAAC;KAC/B,GACC,OAAO,CAAC,IAAI,CAAC;CAiBhB"}
package/dist/index.cjs CHANGED
@@ -3928,7 +3928,7 @@ async function generateSplitTypeScriptFiles(componentHierarchyMap, vueFilesPathM
3928
3928
  customPomImportAliases: options.customPomImportAliases,
3929
3929
  customPomImportNameCollisionBehavior: options.customPomImportNameCollisionBehavior
3930
3930
  });
3931
- const runtimeBasePagePath = path.join(base, "_pom-runtime", "class-generation", "BasePage.ts");
3931
+ const runtimeBasePagePath = path.join(base, "_pom-runtime", "class-generation", "base-page.ts");
3932
3932
  const files = [];
3933
3933
  for (const [name, deps] of entries) {
3934
3934
  const filePath = generatedTsFilePathByComponent.get(name);
@@ -5077,7 +5077,7 @@ function getRuntimeGeneratedAssetSpecs(baseDir, basePageClassPath) {
5077
5077
  const runtimeDirAbs = path.join(baseDir, "_pom-runtime");
5078
5078
  const runtimeClassGenAbs = path.join(runtimeDirAbs, "class-generation");
5079
5079
  const runtimeClassGenSourceDir = resolvePluginAsset("../class-generation");
5080
- const runtimeClassGenFiles = fs.readdirSync(runtimeClassGenSourceDir).filter((file) => file.endsWith(".ts")).filter((file) => file !== "BasePage.ts" && file !== "index.ts").sort((left, right) => left.localeCompare(right));
5080
+ const runtimeClassGenFiles = fs.readdirSync(runtimeClassGenSourceDir).filter((file) => file.endsWith(".ts")).filter((file) => file !== "base-page.ts" && file !== "index.ts").sort((left, right) => left.localeCompare(right));
5081
5081
  return [
5082
5082
  {
5083
5083
  absolutePath: resolvePluginAsset("../click-instrumentation.ts"),
@@ -5091,8 +5091,8 @@ function getRuntimeGeneratedAssetSpecs(baseDir, basePageClassPath) {
5091
5091
  })),
5092
5092
  {
5093
5093
  absolutePath: basePageClassPath,
5094
- description: "BasePage.ts",
5095
- outputPath: path.join(runtimeClassGenAbs, "BasePage.ts")
5094
+ description: "base-page.ts",
5095
+ outputPath: path.join(runtimeClassGenAbs, "base-page.ts")
5096
5096
  }
5097
5097
  ];
5098
5098
  }
@@ -5259,12 +5259,13 @@ async function generateAggregatedFiles(componentHierarchyMap, vueFilesPathMap, b
5259
5259
  const runtimeDirRel = "./_pom-runtime";
5260
5260
  const runtimeClassGenRel = `${runtimeDirRel}/class-generation`;
5261
5261
  imports.push(`import type { PwLocator, PwPage } from "${runtimeClassGenRel}/playwright-types";`);
5262
- imports.push(`import { BasePage } from "${runtimeClassGenRel}/BasePage";`);
5263
- imports.push(`import type { Fluent } from "${runtimeClassGenRel}/BasePage";`);
5262
+ imports.push(`import { BasePage } from "${runtimeClassGenRel}/base-page";`);
5263
+ imports.push(`import type { Fluent } from "${runtimeClassGenRel}/base-page";`);
5264
5264
  imports.push(`export * from "${runtimeDirRel}/click-instrumentation";`);
5265
5265
  imports.push(`export * from "${runtimeClassGenRel}/playwright-types";`);
5266
- imports.push(`export * from "${runtimeClassGenRel}/Pointer";`);
5267
- imports.push(`export * from "${runtimeClassGenRel}/BasePage";`);
5266
+ imports.push(`export * from "${runtimeClassGenRel}/callout";`);
5267
+ imports.push(`export * from "${runtimeClassGenRel}/pointer";`);
5268
+ imports.push(`export * from "${runtimeClassGenRel}/base-page";`);
5268
5269
  const customPomImportResolution = resolveCustomPomImportResolution(generatedClassNames, projectRoot, {
5269
5270
  customPomDir: options.customPomDir,
5270
5271
  customPomImportAliases: options.customPomImportAliases,
@@ -6823,14 +6824,19 @@ function createBuildProcessorPlugin(options) {
6823
6824
  return null;
6824
6825
  });
6825
6826
  if (!fs.existsSync(basePageClassPath)) {
6826
- this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
6827
+ this.error(`Base page runtime file not found at ${basePageClassPath}. Ensure it is included in the build.`);
6827
6828
  }
6828
6829
  this.addWatchFile(basePageClassPath);
6829
- const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
6830
+ const pointerPath = path.resolve(path.dirname(basePageClassPath), "pointer.ts");
6830
6831
  if (!fs.existsSync(pointerPath)) {
6831
- this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
6832
+ this.error(`pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
6832
6833
  }
6833
6834
  this.addWatchFile(pointerPath);
6835
+ const calloutPath = path.resolve(path.dirname(basePageClassPath), "callout.ts");
6836
+ if (!fs.existsSync(calloutPath)) {
6837
+ this.error(`callout.ts not found at ${calloutPath}. Ensure it is included in the build.`);
6838
+ }
6839
+ this.addWatchFile(calloutPath);
6834
6840
  },
6835
6841
  async buildEnd(error) {
6836
6842
  if (error) {
@@ -7163,7 +7169,14 @@ function createDevProcessorPlugin(options) {
7163
7169
  };
7164
7170
  const watchedVueGlobs = scanDirs.map((dir) => path.resolve(projectRootRef.current, dir, "**", "*.vue"));
7165
7171
  const watchedPluginGlob = path.resolve(projectRootRef.current, "vite-plugins", "vue-pom-generator", "**", "*.ts");
7166
- server.watcher.add([...watchedVueGlobs, watchedPluginGlob, basePageClassPath]);
7172
+ const runtimeDir = path.dirname(basePageClassPath);
7173
+ server.watcher.add([
7174
+ ...watchedVueGlobs,
7175
+ watchedPluginGlob,
7176
+ basePageClassPath,
7177
+ path.resolve(runtimeDir, "pointer.ts"),
7178
+ path.resolve(runtimeDir, "callout.ts")
7179
+ ]);
7167
7180
  scheduleVueFileRegenLocal = (filePath, source) => {
7168
7181
  pendingChangedVueFiles.add(filePath);
7169
7182
  logDebug(`queued(${source}): files=${pendingChangedVueFiles.size} deleted=${pendingDeletedComponents.size}`);
@@ -7352,9 +7365,9 @@ function createSupportPlugins(options) {
7352
7365
  const resolvedRouterEntry = resolveRouterEntry2();
7353
7366
  const getDefaultBasePageClassPath = () => {
7354
7367
  try {
7355
- return node_url.fileURLToPath(new URL("../class-generation/BasePage.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
7368
+ return node_url.fileURLToPath(new URL("../class-generation/base-page.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
7356
7369
  } catch {
7357
- return path.resolve(__dirname, "..", "class-generation", "BasePage.ts");
7370
+ return path.resolve(__dirname, "..", "class-generation", "base-page.ts");
7358
7371
  }
7359
7372
  };
7360
7373
  const basePageClassPath = basePageClassPathOverride ?? getDefaultBasePageClassPath();