@immense/vue-pom-generator 1.0.10 → 1.0.11

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,28 +1,26 @@
1
1
  ● ## Highlights
2
- - Adopt native Playwright Page and Locator types for PwPage and PwLocator.
3
- - Add test for existingIdBehavior error handling.
4
- - Improve type safety in tests by replacing any with specific types.
5
- - Fix type error in existing-id-error.test.ts.
6
- - Updates across class-generation and plugin modules.
2
+ - TestID click instrumentation is now optional by default.
3
+ - Fixed packaged runtime type path resolution.
4
+ - Aggregate mode now emits runtime dependencies.
5
+ - Updates across BasePage and method generation to support new behavior.
7
6
 
8
7
  ## Changes
9
- - Types
10
- - Use native Playwright Page/Locator for PwPage/PwLocator (class-generation/index.ts,
11
- class-generation/playwright-types.ts)
12
- - Tests
13
- - Add tests/existing-id-error.test.ts for existingIdBehavior error handling
14
- - Fix type error in tests/existing-id-error.test.ts
15
- - Update tests/utils-coverage.test.ts
16
- - Plugin
17
- - Update plugin/vue-plugin.ts
18
- - Tooling/Config
19
- - Update eslint.config.ts
20
- - Update package.json
8
+ - Instrumentation
9
+ - Make TestID click instrumentation optional by default (method-generation.ts updates).
10
+ - Runtime packaging and dependencies
11
+ - Fix resolution of packaged runtime type paths.
12
+ - Emit runtime dependencies in aggregate mode.
13
+ - Code updates
14
+ - Modified class-generation/BasePage.ts and class-generation/index.ts.
15
+ - package.json updated.
16
+
17
+ ## Breaking Changes
18
+ - None noted.
21
19
 
22
20
  ## Pull Requests Included
23
21
  - #1 Add PR release-notes preview comments — https://github.com/immense/vue-pom-generator/pull/1
24
22
  (by @dkattan)
25
23
 
26
24
  ## Testing
27
- - New test added and existing tests updated; type errors addressed.
25
+ - No testing changes or additions mentioned.
28
26
 
@@ -4,8 +4,15 @@ import type { TestIdClickEventDetail } from "../click-instrumentation";
4
4
  import { Pointer } from "./Pointer";
5
5
  import type { AfterPointerClick, AfterPointerClickInfo } from "./Pointer";
6
6
 
7
- // Click instrumentation is a core contract for generated POMs.
8
- const REQUIRE_CLICK_EVENT = true;
7
+ // Click instrumentation is optional for generated POMs.
8
+ //
9
+ // When enabled, POM click/fill helpers will wait for the app to emit
10
+ // `__testid_event__` { testId, phase: "after" } after interacting with an
11
+ // element that has a data-testid.
12
+ //
13
+ // Default: disabled. (Playwright already has robust auto-waiting; requiring a
14
+ // custom event makes tests depend on app runtime instrumentation.)
15
+ const REQUIRE_CLICK_EVENT = false;
9
16
 
10
17
  // Keep logging off by default.
11
18
  const CLICK_EVENT_DEBUG = false;
@@ -97,6 +104,10 @@ export class BasePage {
97
104
  }
98
105
 
99
106
  private async waitForTestIdClickEventAfter(testId: string, options?: { timeoutMs?: number }): Promise<void> {
107
+ if (!REQUIRE_CLICK_EVENT) {
108
+ return;
109
+ }
110
+
100
111
  const timeoutMs = options?.timeoutMs ?? 2_000;
101
112
  const requireEvent = REQUIRE_CLICK_EVENT;
102
113
 
@@ -1163,133 +1163,21 @@ async function generateAggregatedFiles(
1163
1163
  throw new Error("basePageClassPath is required for aggregated generation");
1164
1164
  }
1165
1165
 
1166
- // Inline BasePage into the aggregated output.
1166
+ // Aggregate mode goal: consolidate all generated POM classes into one file.
1167
+ // Instead of inlining BasePage/Pointer helpers and stripping imports via regex, we
1168
+ // emit/copy those dependencies into the output folder and import them normally.
1167
1169
  //
1168
- // Why:
1169
- // - Playwright's runtime loader can treat workspace packages (like `vue-pom-generator`)
1170
- // as external and not apply TS transforms/module resolution consistently.
1171
- // - Importing a .ts file from inside a "type": "module" package can fail with
1172
- // "Cannot find module" at runtime.
1173
- //
1174
- // Inlining keeps the generated POMs self-contained and stable across platforms.
1175
- const clickInstrumentationInline = [
1176
- "export const TESTID_CLICK_EVENT_NAME = \"__testid_event__\";",
1177
- "export const TESTID_CLICK_EVENT_STRICT_FLAG = \"__testid_click_event_strict__\";",
1178
- "export interface TestIdClickEventDetail {",
1179
- " testId?: string;",
1180
- " phase?: \"before\" | \"after\" | \"error\" | string;",
1181
- " err?: string;",
1182
- "}",
1183
- ].join("\n");
1184
-
1185
- const inlinePlaywrightTypesModule = () => {
1186
- const typesPath = fileURLToPath(new URL("./playwright-types.ts", import.meta.url));
1187
-
1188
- let typesSource = "";
1189
- try {
1190
- typesSource = fs.readFileSync(typesPath, "utf8");
1191
- }
1192
- catch {
1193
- throw new Error(`Failed to read playwright-types.ts at ${typesPath}`);
1194
- }
1195
-
1196
- // Strip the import from the inlined types.
1197
- typesSource = typesSource.replace(
1198
- /import\s+type\s*\{\s*Locator\s+as\s+PwLocator\s*,\s*Page\s+as\s+PwPage\s*\}\s*from\s*["']@playwright\/test["'];?\s*/,
1199
- "",
1200
- );
1201
-
1202
- return typesSource.trim();
1203
- };
1204
-
1205
- const inlinePointerModule = () => {
1206
- // Inline Pointer.ts from this package so generated POMs are self-contained and do not
1207
- // rely on runtime TS module resolution within workspace packages.
1208
- const pointerPath = fileURLToPath(new URL("./Pointer.ts", import.meta.url));
1209
-
1210
- let pointerSource = "";
1211
- try {
1212
- pointerSource = fs.readFileSync(pointerPath, "utf8");
1213
- }
1214
- catch {
1215
- throw new Error(`Failed to read Pointer.ts at ${pointerPath}`);
1216
- }
1217
-
1218
- // Replace the click-instrumentation import with an inline copy.
1219
- pointerSource = pointerSource.replace(
1220
- /import\s*\{[\s\S]*?\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/,
1221
- `${clickInstrumentationInline}\n\n`,
1222
- );
1223
-
1224
- // If Pointer uses a split value import + type-only import, remove the type-only import too.
1225
- // The inline block already declares TestIdClickEventDetail.
1226
- pointerSource = pointerSource.replace(
1227
- /import\s+type\s*\{\s*TestIdClickEventDetail\s*\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/g,
1228
- "",
1229
- );
1230
-
1231
- // The aggregated file already imports these Playwright types once at the top.
1232
- pointerSource = pointerSource.replace(
1233
- /import\s+type\s*\{\s*Locator\s+as\s+PwLocator\s*,\s*Page\s+as\s+PwPage\s*\}\s*from\s*["']@playwright\/test["'];?\s*/,
1234
- "",
1235
- );
1236
-
1237
- // The aggregated file inlines these structural types once at the top.
1238
- pointerSource = pointerSource.replace(
1239
- /import\s+type\s*\{\s*PwLocator\s*,\s*PwPage\s*\}\s*from\s*["']\.\/playwright-types["'];?\s*/,
1240
- "",
1241
- );
1242
-
1243
- return pointerSource.trim();
1244
- };
1245
-
1246
- const inlineBasePageModule = () => {
1247
- let basePageSource = "";
1248
- try {
1249
- basePageSource = fs.readFileSync(basePageClassPath, "utf8");
1250
- }
1251
- catch {
1252
- throw new Error(`Failed to read BasePage.ts at ${basePageClassPath}`);
1253
- }
1254
-
1255
- // Replace the click-instrumentation import with an inline copy.
1256
- basePageSource = basePageSource.replace(
1257
- /import\s*\{[\s\S]*?\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/,
1258
- `${clickInstrumentationInline}\n\n`,
1259
- );
1260
-
1261
- // If BasePage uses a split value import + type-only import, remove the type-only import too.
1262
- // The inline block already declares TestIdClickEventDetail.
1263
- basePageSource = basePageSource.replace(
1264
- /import\s+type\s*\{\s*TestIdClickEventDetail\s*\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/g,
1265
- "",
1266
- );
1267
-
1268
- // The aggregated file already imports these Playwright types once at the top.
1269
- // Remove BasePage's own import to avoid duplicate identifiers.
1270
- basePageSource = basePageSource.replace(
1271
- /import\s+type\s*\{\s*Locator\s+as\s+PwLocator\s*,\s*Page\s+as\s+PwPage\s*\}\s*from\s*["']@playwright\/test["'];?\s*/,
1272
- "",
1273
- );
1274
-
1275
- // The aggregated file inlines these structural types once at the top.
1276
- basePageSource = basePageSource.replace(
1277
- /import\s+type\s*\{\s*PwLocator\s*,\s*PwPage\s*\}\s*from\s*["']\.\/playwright-types["'];?\s*/,
1278
- "",
1279
- );
1280
-
1281
- // BasePage references Pointer, but in aggregated output we inline Pointer above.
1282
- basePageSource = basePageSource.replace(
1283
- /import\s+(?:type\s*)?\{[\s\S]*?\}\s*from\s*["']\.\/Pointer["'];?\s*/g,
1284
- "",
1285
- );
1286
-
1287
- return basePageSource.trim();
1288
- };
1289
-
1290
- const playwrightTypesInline = inlinePlaywrightTypesModule();
1291
- const pointerInline = inlinePointerModule();
1292
- const basePageInline = inlineBasePageModule();
1170
+ // This keeps output deterministic and avoids fragile source rewriting.
1171
+ const runtimeDirRel = "./_pom-runtime";
1172
+ const runtimeClassGenRel = `${runtimeDirRel}/class-generation`;
1173
+
1174
+ imports.push(`import type { PwLocator, PwPage } from "${runtimeClassGenRel}/playwright-types";`);
1175
+ imports.push(`import { BasePage } from "${runtimeClassGenRel}/BasePage";`);
1176
+ imports.push(`import type { Fluent } from "${runtimeClassGenRel}/BasePage";`);
1177
+ imports.push(`export * from "${runtimeDirRel}/click-instrumentation";`);
1178
+ imports.push(`export * from "${runtimeClassGenRel}/playwright-types";`);
1179
+ imports.push(`export * from "${runtimeClassGenRel}/Pointer";`);
1180
+ imports.push(`export * from "${runtimeClassGenRel}/BasePage";`);
1293
1181
 
1294
1182
  // Handwritten POM helpers for complicated/third-party widgets.
1295
1183
  // Convention: place them in `tests/playwright/pom/custom/*.ts`.
@@ -1545,13 +1433,6 @@ async function generateAggregatedFiles(
1545
1433
  const baseContent = [
1546
1434
  header,
1547
1435
  ...imports,
1548
- "",
1549
- playwrightTypesInline,
1550
- "",
1551
- pointerInline,
1552
- "",
1553
- basePageInline,
1554
- "",
1555
1436
  ...classes,
1556
1437
  ...(stubs.length ? ["", ...stubs] : []),
1557
1438
  ].filter(Boolean).join("\n\n");
@@ -1561,15 +1442,56 @@ async function generateAggregatedFiles(
1561
1442
 
1562
1443
  const base = ensureDir(outDir);
1563
1444
  const outputFile = path.join(base, "page-object-models.g.ts");
1564
- const header = `/// <reference lib="es2015" />\n${eslintSuppressionHeader}import type { Locator as PwLocator, Page as PwPage } from "@playwright/test";\n/**\n * Aggregated generated POMs\n${AUTO_GENERATED_COMMENT}`;
1445
+ const header = `/// <reference lib="es2015" />\n${eslintSuppressionHeader}/**\n * Aggregated generated POMs\n${AUTO_GENERATED_COMMENT}`;
1565
1446
  const content = makeAggregatedContent(header, path.dirname(outputFile), [...views, ...components]);
1566
1447
 
1567
1448
  const indexFile = path.join(base, "index.ts");
1568
1449
  const indexContent = `${eslintSuppressionHeader}/**\n * POM exports\n${AUTO_GENERATED_COMMENT}\n\nexport * from "./page-object-models.g";\n`;
1569
1450
 
1451
+ const runtimeDirAbs = path.join(base, "_pom-runtime");
1452
+ const runtimeClassGenAbs = path.join(runtimeDirAbs, "class-generation");
1453
+
1454
+ const readText = (absPath: string, description: string) => {
1455
+ try {
1456
+ return fs.readFileSync(absPath, "utf8");
1457
+ }
1458
+ catch {
1459
+ throw new Error(`Failed to read ${description} at ${absPath}`);
1460
+ }
1461
+ };
1462
+
1463
+ // Copy runtime dependencies into the output folder so the aggregated POM file can
1464
+ // import them without relying on workspace package resolution.
1465
+ const clickInstrumentationAbs = fileURLToPath(new URL("../click-instrumentation.ts", import.meta.url));
1466
+ // These runtime .ts files must resolve correctly both when running from source
1467
+ // (e.g. during development/tests) and when bundled into dist/index.* for npm.
1468
+ // Resolving via package-root `class-generation/*` is stable across both.
1469
+ const pointerAbs = fileURLToPath(new URL("../class-generation/Pointer.ts", import.meta.url));
1470
+ const playwrightTypesAbs = fileURLToPath(new URL("../class-generation/playwright-types.ts", import.meta.url));
1471
+
1472
+ const runtimeFiles: Array<{ filePath: string; content: string }> = [
1473
+ {
1474
+ filePath: path.join(runtimeDirAbs, "click-instrumentation.ts"),
1475
+ content: readText(clickInstrumentationAbs, "click-instrumentation.ts"),
1476
+ },
1477
+ {
1478
+ filePath: path.join(runtimeClassGenAbs, "Pointer.ts"),
1479
+ content: readText(pointerAbs, "Pointer.ts"),
1480
+ },
1481
+ {
1482
+ filePath: path.join(runtimeClassGenAbs, "playwright-types.ts"),
1483
+ content: readText(playwrightTypesAbs, "playwright-types.ts"),
1484
+ },
1485
+ {
1486
+ filePath: path.join(runtimeClassGenAbs, "BasePage.ts"),
1487
+ content: readText(basePageClassPath, "BasePage.ts"),
1488
+ },
1489
+ ];
1490
+
1570
1491
  return [
1571
1492
  { filePath: outputFile, content },
1572
1493
  { filePath: indexFile, content: indexContent },
1494
+ ...runtimeFiles,
1573
1495
  ];
1574
1496
  }
1575
1497
 
@@ -0,0 +1,14 @@
1
+ // Shared click-instrumentation contract between the Vue template transform and
2
+ // the generated Playwright Page Object Model runtime.
3
+
4
+ export const TESTID_CLICK_EVENT_NAME = "__testid_event__";
5
+
6
+ // When strict mode is enabled, the injected click wrapper will fail fast if it
7
+ // cannot emit the expected event.
8
+ export const TESTID_CLICK_EVENT_STRICT_FLAG = "__testid_click_event_strict__";
9
+
10
+ export interface TestIdClickEventDetail {
11
+ testId?: string;
12
+ phase?: "before" | "after" | "error" | string;
13
+ err?: string;
14
+ }
package/dist/index.cjs CHANGED
@@ -151,8 +151,10 @@ function testIdExpression(formattedDataTestId) {
151
151
  function generateClickMethod(methodName, formattedDataTestId, alternateFormattedDataTestIds, params) {
152
152
  let content;
153
153
  const name = `click${methodName}`;
154
+ const noWaitName = `${name}NoWait`;
154
155
  const paramBlock = formatParams(params);
155
156
  const paramBlockWithWait = paramBlock ? `${paramBlock}, wait: boolean = true` : "wait: boolean = true";
157
+ const argsForForward = Object.keys(params).join(", ");
156
158
  const alternates = uniqueAlternates(formattedDataTestId, alternateFormattedDataTestIds);
157
159
  if (alternates.length > 0) {
158
160
  const candidatesExpr = [formattedDataTestId, ...alternates].map(testIdExpression).join(", ");
@@ -174,6 +176,13 @@ ${INDENT3}}
174
176
  ${INDENT2}}
175
177
  ${INDENT2}throw (lastError instanceof Error) ? lastError : new Error("[pom] Failed to click any candidate locator for ${name}.");
176
178
  ${INDENT}}
179
+ `;
180
+ const noWaitSig = hasParam(params, "key") ? paramBlock : "";
181
+ const noWaitArgs = argsForForward ? `${argsForForward}, false` : "false";
182
+ content += `
183
+ ${INDENT}async ${noWaitName}(${noWaitSig}) {
184
+ ${INDENT2}await this.${name}(${noWaitArgs});
185
+ ${INDENT}}
177
186
  `;
178
187
  return content;
179
188
  }
@@ -181,11 +190,21 @@ ${INDENT}}
181
190
  content = `${INDENT}async ${name}(${paramBlockWithWait}) {
182
191
  ${INDENT2}await this.clickByTestId(\`${formattedDataTestId}\`, "", wait);
183
192
  ${INDENT}}
193
+ `;
194
+ content += `
195
+ ${INDENT}async ${noWaitName}(${paramBlock}) {
196
+ ${INDENT2}await this.${name}(${argsForForward}, false);
197
+ ${INDENT}}
184
198
  `;
185
199
  } else {
186
200
  content = `${INDENT}async ${name}(wait: boolean = true) {
187
201
  ${INDENT2}await this.clickByTestId("${formattedDataTestId}", "", wait);
188
202
  ${INDENT}}
203
+ `;
204
+ content += `
205
+ ${INDENT}async ${noWaitName}() {
206
+ ${INDENT2}await this.${name}(false);
207
+ ${INDENT}}
189
208
  `;
190
209
  }
191
210
  return content;
@@ -3445,91 +3464,15 @@ async function generateAggregatedFiles(componentHierarchyMap, vueFilesPathMap, b
3445
3464
  if (!basePageClassPath) {
3446
3465
  throw new Error("basePageClassPath is required for aggregated generation");
3447
3466
  }
3448
- const clickInstrumentationInline = [
3449
- 'export const TESTID_CLICK_EVENT_NAME = "__testid_event__";',
3450
- 'export const TESTID_CLICK_EVENT_STRICT_FLAG = "__testid_click_event_strict__";',
3451
- "export interface TestIdClickEventDetail {",
3452
- " testId?: string;",
3453
- ' phase?: "before" | "after" | "error" | string;',
3454
- " err?: string;",
3455
- "}"
3456
- ].join("\n");
3457
- const inlinePlaywrightTypesModule = () => {
3458
- const typesPath = node_url.fileURLToPath(new URL("./playwright-types.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
3459
- let typesSource = "";
3460
- try {
3461
- typesSource = fs.readFileSync(typesPath, "utf8");
3462
- } catch {
3463
- throw new Error(`Failed to read playwright-types.ts at ${typesPath}`);
3464
- }
3465
- typesSource = typesSource.replace(
3466
- /import\s+type\s*\{\s*Locator\s+as\s+PwLocator\s*,\s*Page\s+as\s+PwPage\s*\}\s*from\s*["']@playwright\/test["'];?\s*/,
3467
- ""
3468
- );
3469
- return typesSource.trim();
3470
- };
3471
- const inlinePointerModule = () => {
3472
- const pointerPath = node_url.fileURLToPath(new URL("./Pointer.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
3473
- let pointerSource = "";
3474
- try {
3475
- pointerSource = fs.readFileSync(pointerPath, "utf8");
3476
- } catch {
3477
- throw new Error(`Failed to read Pointer.ts at ${pointerPath}`);
3478
- }
3479
- pointerSource = pointerSource.replace(
3480
- /import\s*\{[\s\S]*?\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/,
3481
- `${clickInstrumentationInline}
3482
-
3483
- `
3484
- );
3485
- pointerSource = pointerSource.replace(
3486
- /import\s+type\s*\{\s*TestIdClickEventDetail\s*\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/g,
3487
- ""
3488
- );
3489
- pointerSource = pointerSource.replace(
3490
- /import\s+type\s*\{\s*Locator\s+as\s+PwLocator\s*,\s*Page\s+as\s+PwPage\s*\}\s*from\s*["']@playwright\/test["'];?\s*/,
3491
- ""
3492
- );
3493
- pointerSource = pointerSource.replace(
3494
- /import\s+type\s*\{\s*PwLocator\s*,\s*PwPage\s*\}\s*from\s*["']\.\/playwright-types["'];?\s*/,
3495
- ""
3496
- );
3497
- return pointerSource.trim();
3498
- };
3499
- const inlineBasePageModule = () => {
3500
- let basePageSource = "";
3501
- try {
3502
- basePageSource = fs.readFileSync(basePageClassPath, "utf8");
3503
- } catch {
3504
- throw new Error(`Failed to read BasePage.ts at ${basePageClassPath}`);
3505
- }
3506
- basePageSource = basePageSource.replace(
3507
- /import\s*\{[\s\S]*?\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/,
3508
- `${clickInstrumentationInline}
3509
-
3510
- `
3511
- );
3512
- basePageSource = basePageSource.replace(
3513
- /import\s+type\s*\{\s*TestIdClickEventDetail\s*\}\s*from\s*["']\.\.\/click-instrumentation["'];?\s*/g,
3514
- ""
3515
- );
3516
- basePageSource = basePageSource.replace(
3517
- /import\s+type\s*\{\s*Locator\s+as\s+PwLocator\s*,\s*Page\s+as\s+PwPage\s*\}\s*from\s*["']@playwright\/test["'];?\s*/,
3518
- ""
3519
- );
3520
- basePageSource = basePageSource.replace(
3521
- /import\s+type\s*\{\s*PwLocator\s*,\s*PwPage\s*\}\s*from\s*["']\.\/playwright-types["'];?\s*/,
3522
- ""
3523
- );
3524
- basePageSource = basePageSource.replace(
3525
- /import\s+(?:type\s*)?\{[\s\S]*?\}\s*from\s*["']\.\/Pointer["'];?\s*/g,
3526
- ""
3527
- );
3528
- return basePageSource.trim();
3529
- };
3530
- const playwrightTypesInline = inlinePlaywrightTypesModule();
3531
- const pointerInline = inlinePointerModule();
3532
- const basePageInline = inlineBasePageModule();
3467
+ const runtimeDirRel = "./_pom-runtime";
3468
+ const runtimeClassGenRel = `${runtimeDirRel}/class-generation`;
3469
+ imports.push(`import type { PwLocator, PwPage } from "${runtimeClassGenRel}/playwright-types";`);
3470
+ imports.push(`import { BasePage } from "${runtimeClassGenRel}/BasePage";`);
3471
+ imports.push(`import type { Fluent } from "${runtimeClassGenRel}/BasePage";`);
3472
+ imports.push(`export * from "${runtimeDirRel}/click-instrumentation";`);
3473
+ imports.push(`export * from "${runtimeClassGenRel}/playwright-types";`);
3474
+ imports.push(`export * from "${runtimeClassGenRel}/Pointer";`);
3475
+ imports.push(`export * from "${runtimeClassGenRel}/BasePage";`);
3533
3476
  const addCustomPomImports = () => {
3534
3477
  const importAliases = {
3535
3478
  Toggle: "ToggleWidget",
@@ -3716,13 +3659,6 @@ async function generateAggregatedFiles(componentHierarchyMap, vueFilesPathMap, b
3716
3659
  const baseContent = [
3717
3660
  header2,
3718
3661
  ...imports,
3719
- "",
3720
- playwrightTypesInline,
3721
- "",
3722
- pointerInline,
3723
- "",
3724
- basePageInline,
3725
- "",
3726
3662
  ...classes,
3727
3663
  ...stubs.length ? ["", ...stubs] : []
3728
3664
  ].filter(Boolean).join("\n\n");
@@ -3731,8 +3667,7 @@ async function generateAggregatedFiles(componentHierarchyMap, vueFilesPathMap, b
3731
3667
  const base = ensureDir(outDir);
3732
3668
  const outputFile = path.join(base, "page-object-models.g.ts");
3733
3669
  const header = `/// <reference lib="es2015" />
3734
- ${eslintSuppressionHeader}import type { Locator as PwLocator, Page as PwPage } from "@playwright/test";
3735
- /**
3670
+ ${eslintSuppressionHeader}/**
3736
3671
  * Aggregated generated POMs
3737
3672
  ${AUTO_GENERATED_COMMENT}`;
3738
3673
  const content = makeAggregatedContent(header, path.dirname(outputFile), [...views, ...components]);
@@ -3743,9 +3678,40 @@ ${AUTO_GENERATED_COMMENT}
3743
3678
 
3744
3679
  export * from "./page-object-models.g";
3745
3680
  `;
3681
+ const runtimeDirAbs = path.join(base, "_pom-runtime");
3682
+ const runtimeClassGenAbs = path.join(runtimeDirAbs, "class-generation");
3683
+ const readText = (absPath, description) => {
3684
+ try {
3685
+ return fs.readFileSync(absPath, "utf8");
3686
+ } catch {
3687
+ throw new Error(`Failed to read ${description} at ${absPath}`);
3688
+ }
3689
+ };
3690
+ const clickInstrumentationAbs = node_url.fileURLToPath(new URL("../click-instrumentation.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
3691
+ const pointerAbs = node_url.fileURLToPath(new URL("../class-generation/Pointer.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
3692
+ const playwrightTypesAbs = node_url.fileURLToPath(new URL("../class-generation/playwright-types.ts", typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
3693
+ const runtimeFiles = [
3694
+ {
3695
+ filePath: path.join(runtimeDirAbs, "click-instrumentation.ts"),
3696
+ content: readText(clickInstrumentationAbs, "click-instrumentation.ts")
3697
+ },
3698
+ {
3699
+ filePath: path.join(runtimeClassGenAbs, "Pointer.ts"),
3700
+ content: readText(pointerAbs, "Pointer.ts")
3701
+ },
3702
+ {
3703
+ filePath: path.join(runtimeClassGenAbs, "playwright-types.ts"),
3704
+ content: readText(playwrightTypesAbs, "playwright-types.ts")
3705
+ },
3706
+ {
3707
+ filePath: path.join(runtimeClassGenAbs, "BasePage.ts"),
3708
+ content: readText(basePageClassPath, "BasePage.ts")
3709
+ }
3710
+ ];
3746
3711
  return [
3747
3712
  { filePath: outputFile, content },
3748
- { filePath: indexFile, content: indexContent }
3713
+ { filePath: indexFile, content: indexContent },
3714
+ ...runtimeFiles
3749
3715
  ];
3750
3716
  }
3751
3717
  function createFile(filePath, content) {