@immense/vue-pom-generator 1.0.56 → 1.0.58

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/README.md CHANGED
@@ -54,7 +54,7 @@ export class UserEditorPage extends BasePage {
54
54
  get SaveButton() { /* Playwright locator */ }
55
55
 
56
56
  async typeEmailAddress(text: string, annotationText = "") { /* ... */ }
57
- async clickSave(wait: boolean = true) { /* ... */ }
57
+ async clickSave(wait: boolean = true, annotationText = "") { /* ... */ }
58
58
  }
59
59
  ```
60
60
 
package/RELEASE_NOTES.md CHANGED
@@ -1,15 +1,31 @@
1
- ## Highlights
1
+ I'll fetch the actual commits and PRs between v1.0.57 and HEAD to generate accurate release
2
+ notes.
2
3
 
3
- - Added support for awaited handler wrappers in POM generation
4
- - Enhanced async/await pattern detection in Vue event handlers
5
- - Improved test coverage with 39 new test lines across transform and utils
4
+ Based on the commit range v1.0.57..HEAD, only PR #19 is included in this release. Here are the
5
+ release notes:
6
+
7
+ ---
8
+
9
+ ## Highlights
10
+
11
+ - Pass annotation text through generated click helpers for better test documentation
12
+ - Resolve Vue compiler and Nuxt kit dependencies from consuming app setups instead of the
13
+ plugin's own tree
14
+ - Centralize Playwright video dimension configuration for consistent local and CI test
15
+ recordings
6
16
 
7
17
  ## Changes
8
18
 
9
- - **Handler Detection:** `utils.ts` now correctly identifies and processes event handlers
10
- wrapped in `await` expressions
11
- - **Test Coverage:** Added comprehensive tests for awaited handler scenarios in
12
- `transform.test.ts` and `utils-coverage.test.ts`
19
+ **Local integration hardening:**
20
+ - Generated click helpers now accept and document annotation text parameters
21
+ - Resolve `@vue/compiler-sfc.parse` and `@nuxt/kit` from real consuming-app setups to avoid
22
+ version mismatches
23
+ - Add centralized Playwright video dimensions configuration (`playwright-video-dimensions.json`)
24
+ - Add script to normalize Playwright video settings across local config and CI environments
25
+
26
+ **Test coverage improvements:**
27
+ - Add regression tests for project-local Nuxt kit loading
28
+ - Enhance Nuxt discovery test coverage with real-world integration scenarios
13
29
 
14
30
  ## Breaking Changes
15
31
 
@@ -17,11 +33,15 @@
17
33
 
18
34
  ## Pull Requests Included
19
35
 
20
- - #17 fix: support awaited handler wrappers
21
- (https://github.com/immense/vue-pom-generator/pull/17) by @dkattan
36
+ - [#19](https://github.com/immense/vue-pom-generator/pull/19) fix: harden local app integration
22
37
 
23
38
  ## Testing
24
39
 
25
- Added 39 lines of new tests covering awaited handler wrapper scenarios and edge cases. All tests
26
- passing.
40
+ Validated with:
41
+ - `npm run lint`
42
+ - `npm run typecheck`
43
+ - `npm run build`
44
+ - `npm test`
45
+
46
+ All tests passing with 258 net lines added across 13 files.
27
47
 
package/dist/index.cjs CHANGED
@@ -104,6 +104,21 @@ function createLogger(options) {
104
104
  };
105
105
  }
106
106
  const requireFromModule = node_module.createRequire(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href);
107
+ function resolveNuxtKitEntry(cwd) {
108
+ const attemptResolvers = [
109
+ node_module.createRequire(path.resolve(cwd, "package.json")),
110
+ requireFromModule
111
+ ];
112
+ let lastError;
113
+ for (const resolver of attemptResolvers) {
114
+ try {
115
+ return resolver.resolve("@nuxt/kit");
116
+ } catch (error) {
117
+ lastError = error instanceof Error ? error : new Error(String(error));
118
+ }
119
+ }
120
+ throw lastError ?? new Error("Unknown module resolution error");
121
+ }
107
122
  function toUniqueResolvedPaths(paths) {
108
123
  return Array.from(new Set(paths.map((value) => path.resolve(value))));
109
124
  }
@@ -214,7 +229,7 @@ async function loadNuxtProjectDiscovery(cwd = process.cwd()) {
214
229
  let loadNuxtConfig;
215
230
  let getLayerDirectories;
216
231
  try {
217
- const nuxtKitEntry = requireFromModule.resolve("@nuxt/kit");
232
+ const nuxtKitEntry = resolveNuxtKitEntry(cwd);
218
233
  ({ loadNuxtConfig, getLayerDirectories } = await import(node_url.pathToFileURL(nuxtKitEntry).href));
219
234
  } catch (error) {
220
235
  throw new TypeError(
@@ -403,7 +418,14 @@ function generateClickMethod(methodName, formattedDataTestId, alternateFormatted
403
418
  const candidatesExpr = [formattedDataTestId, ...alternates].map(testIdExpression).join(", ");
404
419
  const clickMethod = createAsyncMethod(
405
420
  name,
406
- hasParam(params, "key") ? [...baseParameters, createInlineParameter("wait", { type: "boolean", initializer: "true" })] : [createInlineParameter("wait", { type: "boolean", initializer: "true" })],
421
+ hasParam(params, "key") ? [
422
+ ...baseParameters,
423
+ createInlineParameter("wait", { type: "boolean", initializer: "true" }),
424
+ createInlineParameter("annotationText", { type: "string", initializer: '""' })
425
+ ] : [
426
+ createInlineParameter("wait", { type: "boolean", initializer: "true" }),
427
+ createInlineParameter("annotationText", { type: "string", initializer: '""' })
428
+ ],
407
429
  (writer) => {
408
430
  writer.writeLine(`const candidates = [${candidatesExpr}] as const;`);
409
431
  writer.writeLine("let lastError: unknown;");
@@ -411,7 +433,7 @@ function generateClickMethod(methodName, formattedDataTestId, alternateFormatted
411
433
  writer.writeLine("const locator = this.locatorByTestId(testId);");
412
434
  writer.write("try ").block(() => {
413
435
  writer.write("if (await locator.count()) ").block(() => {
414
- writer.writeLine('await this.clickLocator(locator, "", wait);');
436
+ writer.writeLine("await this.clickLocator(locator, annotationText, wait);");
415
437
  writer.writeLine("return;");
416
438
  });
417
439
  });
@@ -422,10 +444,10 @@ function generateClickMethod(methodName, formattedDataTestId, alternateFormatted
422
444
  writer.writeLine(`throw (lastError instanceof Error) ? lastError : new Error("[pom] Failed to click any candidate locator for ${name}.");`);
423
445
  }
424
446
  );
425
- const noWaitArgs = argsForForward ? `${argsForForward}, false` : "false";
447
+ const noWaitArgs = argsForForward ? `${argsForForward}, false, annotationText` : "false, annotationText";
426
448
  const noWaitMethod = createAsyncMethod(
427
449
  noWaitName,
428
- hasParam(params, "key") ? baseParameters : [],
450
+ hasParam(params, "key") ? [...baseParameters, createInlineParameter("annotationText", { type: "string", initializer: '""' })] : [createInlineParameter("annotationText", { type: "string", initializer: '""' })],
429
451
  (writer) => {
430
452
  writer.writeLine(`await this.${name}(${noWaitArgs});`);
431
453
  }
@@ -434,21 +456,44 @@ function generateClickMethod(methodName, formattedDataTestId, alternateFormatted
434
456
  }
435
457
  if (hasParam(params, "key")) {
436
458
  return [
437
- createAsyncMethod(name, [...baseParameters, createInlineParameter("wait", { type: "boolean", initializer: "true" })], (writer) => {
438
- writer.writeLine(`await this.clickByTestId(\`${formattedDataTestId}\`, "", wait);`);
439
- }),
440
- createAsyncMethod(noWaitName, baseParameters, (writer) => {
441
- writer.writeLine(`await this.${name}(${argsForForward}, false);`);
442
- })
459
+ createAsyncMethod(
460
+ name,
461
+ [
462
+ ...baseParameters,
463
+ createInlineParameter("wait", { type: "boolean", initializer: "true" }),
464
+ createInlineParameter("annotationText", { type: "string", initializer: '""' })
465
+ ],
466
+ (writer) => {
467
+ writer.writeLine(`await this.clickByTestId(\`${formattedDataTestId}\`, annotationText, wait);`);
468
+ }
469
+ ),
470
+ createAsyncMethod(
471
+ noWaitName,
472
+ [...baseParameters, createInlineParameter("annotationText", { type: "string", initializer: '""' })],
473
+ (writer) => {
474
+ writer.writeLine(`await this.${name}(${argsForForward}, false, annotationText);`);
475
+ }
476
+ )
443
477
  ];
444
478
  }
445
479
  return [
446
- createAsyncMethod(name, [createInlineParameter("wait", { type: "boolean", initializer: "true" })], (writer) => {
447
- writer.writeLine(`await this.clickByTestId("${formattedDataTestId}", "", wait);`);
448
- }),
449
- createAsyncMethod(noWaitName, [], (writer) => {
450
- writer.writeLine(`await this.${name}(false);`);
451
- })
480
+ createAsyncMethod(
481
+ name,
482
+ [
483
+ createInlineParameter("wait", { type: "boolean", initializer: "true" }),
484
+ createInlineParameter("annotationText", { type: "string", initializer: '""' })
485
+ ],
486
+ (writer) => {
487
+ writer.writeLine(`await this.clickByTestId("${formattedDataTestId}", annotationText, wait);`);
488
+ }
489
+ ),
490
+ createAsyncMethod(
491
+ noWaitName,
492
+ [createInlineParameter("annotationText", { type: "string", initializer: '""' })],
493
+ (writer) => {
494
+ writer.writeLine(`await this.${name}(false, annotationText);`);
495
+ }
496
+ )
452
497
  ];
453
498
  }
454
499
  function generateRadioMethod(methodName, formattedDataTestId) {
@@ -2893,10 +2938,13 @@ Fix: make the element identifiable (e.g. add id/name/inner text or use a more sp
2893
2938
  formattedDataTestId: formattedDataTestIdForPom
2894
2939
  },
2895
2940
  keyLiteral: rawValue,
2896
- params: { wait: "boolean = true" }
2941
+ params: { wait: "boolean = true", annotationText: 'string = ""' }
2897
2942
  });
2898
2943
  if (added) {
2899
- registerGeneratedMethodSignature(generatedName, { params: `wait: boolean = true`, argNames: ["wait"] });
2944
+ registerGeneratedMethodSignature(generatedName, {
2945
+ params: `wait: boolean = true, annotationText: string = ""`,
2946
+ argNames: ["wait", "annotationText"]
2947
+ });
2900
2948
  }
2901
2949
  }
2902
2950
  return;
@@ -3157,6 +3205,56 @@ function createRouterIntrospectionVueStubPlugin(options) {
3157
3205
  }
3158
3206
  };
3159
3207
  }
3208
+ function snapshotGlobalValue(name) {
3209
+ const g = globalThis;
3210
+ return {
3211
+ descriptor: Object.getOwnPropertyDescriptor(globalThis, name),
3212
+ value: g[name]
3213
+ };
3214
+ }
3215
+ function setTemporaryGlobal(name, value, snapshots) {
3216
+ if (!snapshots.has(name))
3217
+ snapshots.set(name, snapshotGlobalValue(name));
3218
+ const snapshot = snapshots.get(name);
3219
+ if (!snapshot)
3220
+ return false;
3221
+ if (!snapshot.descriptor || snapshot.descriptor.configurable) {
3222
+ Object.defineProperty(globalThis, name, {
3223
+ configurable: true,
3224
+ enumerable: snapshot.descriptor?.enumerable ?? true,
3225
+ writable: true,
3226
+ value
3227
+ });
3228
+ return true;
3229
+ }
3230
+ if ("writable" in snapshot.descriptor && snapshot.descriptor.writable) {
3231
+ Reflect.set(globalThis, name, value);
3232
+ return true;
3233
+ }
3234
+ if (snapshot.descriptor.set) {
3235
+ snapshot.descriptor.set.call(globalThis, value);
3236
+ return true;
3237
+ }
3238
+ return false;
3239
+ }
3240
+ function restoreTemporaryGlobals(snapshots) {
3241
+ for (const [name, snapshot] of Array.from(snapshots.entries()).reverse()) {
3242
+ const { descriptor, value } = snapshot;
3243
+ if (!descriptor) {
3244
+ Reflect.deleteProperty(globalThis, name);
3245
+ continue;
3246
+ }
3247
+ if (descriptor.configurable) {
3248
+ Object.defineProperty(globalThis, name, descriptor);
3249
+ continue;
3250
+ }
3251
+ if ("writable" in descriptor && descriptor.writable) {
3252
+ Reflect.set(globalThis, name, value);
3253
+ continue;
3254
+ }
3255
+ descriptor.set?.call(globalThis, value);
3256
+ }
3257
+ }
3160
3258
  const PARAM_TOKEN_PREFIX = "__VUE_TESTID_PARAM__";
3161
3259
  function getParamToken(name) {
3162
3260
  return `${PARAM_TOKEN_PREFIX}${name}__`;
@@ -3505,12 +3603,18 @@ function createMinimalLocation() {
3505
3603
  ancestorOrigins: { length: 0, contains: () => false, item: () => null, [Symbol.iterator]: [][Symbol.iterator] }
3506
3604
  };
3507
3605
  }
3508
- async function ensureDomShim() {
3606
+ function ensureDomShim() {
3509
3607
  const g = globalThis;
3510
3608
  if (typeof document !== "undefined" && typeof window !== "undefined")
3511
- return;
3609
+ return () => {
3610
+ };
3512
3611
  const minimalDoc = createMinimalDocument();
3513
3612
  const minimalLocation = createMinimalLocation();
3613
+ const snapshots = /* @__PURE__ */ new Map();
3614
+ const setGlobal = (name, value) => {
3615
+ if (!setTemporaryGlobal(name, value, snapshots))
3616
+ debugLog(`could not temporarily install global ${name}`);
3617
+ };
3514
3618
  const win = {
3515
3619
  document: minimalDoc,
3516
3620
  location: minimalLocation,
@@ -3555,17 +3659,17 @@ async function ensureDomShim() {
3555
3659
  queueMicrotask,
3556
3660
  performance: globalThis.performance
3557
3661
  };
3558
- g.window = win;
3559
- g.document = minimalDoc;
3560
- g.location = minimalLocation;
3662
+ setGlobal("window", win);
3663
+ setGlobal("document", minimalDoc);
3664
+ setGlobal("location", minimalLocation);
3561
3665
  if (!g.self)
3562
- g.self = win;
3666
+ setGlobal("self", win);
3563
3667
  if (!g.navigator)
3564
- g.navigator = win.navigator;
3668
+ setGlobal("navigator", win.navigator);
3565
3669
  if (!g.history)
3566
- g.history = win.history;
3670
+ setGlobal("history", win.history);
3567
3671
  if (!g.MutationObserver) {
3568
- g.MutationObserver = class {
3672
+ setGlobal("MutationObserver", class {
3569
3673
  disconnect() {
3570
3674
  }
3571
3675
  observe() {
@@ -3573,20 +3677,20 @@ async function ensureDomShim() {
3573
3677
  takeRecords() {
3574
3678
  return [];
3575
3679
  }
3576
- };
3680
+ });
3577
3681
  }
3578
3682
  if (!g.ResizeObserver) {
3579
- g.ResizeObserver = class {
3683
+ setGlobal("ResizeObserver", class {
3580
3684
  disconnect() {
3581
3685
  }
3582
3686
  observe() {
3583
3687
  }
3584
3688
  unobserve() {
3585
3689
  }
3586
- };
3690
+ });
3587
3691
  }
3588
3692
  if (!g.IntersectionObserver) {
3589
- g.IntersectionObserver = class {
3693
+ setGlobal("IntersectionObserver", class {
3590
3694
  disconnect() {
3591
3695
  }
3592
3696
  observe() {
@@ -3596,10 +3700,10 @@ async function ensureDomShim() {
3596
3700
  takeRecords() {
3597
3701
  return [];
3598
3702
  }
3599
- };
3703
+ });
3600
3704
  }
3601
3705
  if (!g.requestIdleCallback) {
3602
- g.requestIdleCallback = (cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 0 }), 1);
3706
+ setGlobal("requestIdleCallback", (cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 0 }), 1));
3603
3707
  }
3604
3708
  if (!g.localStorage || !g.sessionStorage) {
3605
3709
  const storageFactory = () => {
@@ -3622,12 +3726,15 @@ async function ensureDomShim() {
3622
3726
  };
3623
3727
  };
3624
3728
  if (!g.localStorage)
3625
- g.localStorage = storageFactory();
3729
+ setGlobal("localStorage", storageFactory());
3626
3730
  if (!g.sessionStorage)
3627
- g.sessionStorage = storageFactory();
3731
+ setGlobal("sessionStorage", storageFactory());
3628
3732
  }
3629
3733
  if (!g.requestAnimationFrame)
3630
- g.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 16);
3734
+ setGlobal("requestAnimationFrame", (cb) => setTimeout(() => cb(Date.now()), 16));
3735
+ return () => {
3736
+ restoreTemporaryGlobals(snapshots);
3737
+ };
3631
3738
  }
3632
3739
  function unwrapNuxtPageSegment(segment, prefix, suffix) {
3633
3740
  if (!segment.startsWith(prefix) || !segment.endsWith(suffix))
@@ -3745,85 +3852,89 @@ async function parseRouterFileFromCwd(routerEntryPath, options = {}) {
3745
3852
  }
3746
3853
  const cwd = path.dirname(routerEntry);
3747
3854
  const moduleShims = normalizeRouterIntrospectionModuleShims(options.moduleShims);
3748
- await ensureDomShim();
3749
- debugLog(`parseRouterFileFromCwd cwd=${cwd}`);
3750
- const vite = await import("vite");
3751
- const server = await vite.createServer({
3752
- root: cwd,
3753
- configFile: false,
3754
- logLevel: "error",
3755
- // This server is created only to SSR-load the router module. Disable HMR/WebSocket
3756
- // to avoid port conflicts in dev/test environments.
3757
- server: { middlewareMode: true, hmr: false, ws: false },
3758
- appType: "custom",
3759
- // IMPORTANT:
3760
- // This internal, short-lived Vite server exists only to `ssrLoadModule()` the router entry.
3761
- // We close it immediately after reading routes.
3762
- //
3763
- // Vite's dependency optimizer (vite:dep-scan / optimizeDeps) runs asynchronously and can
3764
- // still have pending resolve requests when we call `server.close()`, which surfaces as:
3765
- // "The server is being restarted or closed. Request is outdated [plugin vite:dep-scan]"
3766
- //
3767
- // Disable optimizeDeps entirely for this internal server to avoid that race.
3768
- optimizeDeps: {
3769
- disabled: true
3770
- },
3771
- resolve: {
3772
- alias: {
3773
- "@": cwd
3774
- }
3775
- },
3776
- // Important: Do NOT include @vitejs/plugin-vue here.
3777
- // We stub all `.vue` imports ourselves, and including the Vue plugin would attempt to parse
3778
- // those stubbed modules as real SFCs (and fail).
3779
- plugins: [createRouterIntrospectionVueStubPlugin({ routerEntryAbs: routerEntry, moduleShims })]
3780
- });
3855
+ const restoreDomShim = ensureDomShim();
3781
3856
  try {
3782
- const moduleId = node_url.pathToFileURL(routerEntry).href;
3783
- debugLog(`ssrLoadModule(${moduleId}) start`);
3784
- const mod = await server.ssrLoadModule(moduleId);
3785
- debugLog(`ssrLoadModule(${moduleId}) done; hasDefault=${typeof mod?.default === "function"}`);
3786
- const makeRouter = mod?.default;
3787
- if (typeof makeRouter !== "function") {
3788
- throw new TypeError(`[vue-pom-generator] ${routerEntry} must export a default router factory function (export default makeRouter).`);
3789
- }
3790
- let router;
3857
+ debugLog(`parseRouterFileFromCwd cwd=${cwd}`);
3858
+ const vite = await import("vite");
3859
+ const server = await vite.createServer({
3860
+ root: cwd,
3861
+ configFile: false,
3862
+ logLevel: "error",
3863
+ // This server is created only to SSR-load the router module. Disable HMR/WebSocket
3864
+ // to avoid port conflicts in dev/test environments.
3865
+ server: { middlewareMode: true, hmr: false, ws: false },
3866
+ appType: "custom",
3867
+ // IMPORTANT:
3868
+ // This internal, short-lived Vite server exists only to `ssrLoadModule()` the router entry.
3869
+ // We close it immediately after reading routes.
3870
+ //
3871
+ // Vite's dependency optimizer (vite:dep-scan / optimizeDeps) runs asynchronously and can
3872
+ // still have pending resolve requests when we call `server.close()`, which surfaces as:
3873
+ // "The server is being restarted or closed. Request is outdated [plugin vite:dep-scan]"
3874
+ //
3875
+ // Disable optimizeDeps entirely for this internal server to avoid that race.
3876
+ optimizeDeps: {
3877
+ disabled: true
3878
+ },
3879
+ resolve: {
3880
+ alias: {
3881
+ "@": cwd
3882
+ }
3883
+ },
3884
+ // Important: Do NOT include @vitejs/plugin-vue here.
3885
+ // We stub all `.vue` imports ourselves, and including the Vue plugin would attempt to parse
3886
+ // those stubbed modules as real SFCs (and fail).
3887
+ plugins: [createRouterIntrospectionVueStubPlugin({ routerEntryAbs: routerEntry, moduleShims })]
3888
+ });
3791
3889
  try {
3792
- router = makeRouter();
3793
- } catch (err) {
3794
- throw new Error(`[vue-pom-generator] makeRouter() invocation failed: ${String(err)}`);
3795
- }
3796
- const routeNameMap = /* @__PURE__ */ new Map();
3797
- const routePathMap = /* @__PURE__ */ new Map();
3798
- const routeMetaEntries = [];
3799
- for (const r of router.getRoutes()) {
3800
- const componentInfo = await getComponentInfoFromRouteRecord(r, { rootDir: cwd });
3801
- const componentName = resolveIntrospectedComponentName(componentInfo, options.componentNaming);
3802
- if (!componentName)
3803
- continue;
3804
- if (typeof r.path === "string" && r.path.length) {
3805
- routePathMap.set(r.path, componentName);
3890
+ const moduleId = node_url.pathToFileURL(routerEntry).href;
3891
+ debugLog(`ssrLoadModule(${moduleId}) start`);
3892
+ const mod = await server.ssrLoadModule(moduleId);
3893
+ debugLog(`ssrLoadModule(${moduleId}) done; hasDefault=${typeof mod?.default === "function"}`);
3894
+ const makeRouter = mod?.default;
3895
+ if (typeof makeRouter !== "function") {
3896
+ throw new TypeError(`[vue-pom-generator] ${routerEntry} must export a default router factory function (export default makeRouter).`);
3806
3897
  }
3807
- if (typeof r.name === "string" && r.name.length) {
3808
- const key = toPascalCase(r.name);
3809
- routeNameMap.set(key, componentName);
3898
+ let router;
3899
+ try {
3900
+ router = makeRouter();
3901
+ } catch (err) {
3902
+ throw new Error(`[vue-pom-generator] makeRouter() invocation failed: ${String(err)}`);
3810
3903
  }
3811
- const { paramKeys, queryKeys } = getRoutePropsKeys(r);
3812
- const paramsMeta = getRouteParamMeta(router, r, paramKeys);
3813
- const pathTemplate = buildRouteTemplate(router, r, paramsMeta.map((p) => p.name));
3814
- if (typeof pathTemplate === "string" && pathTemplate.length) {
3815
- routeMetaEntries.push({
3816
- componentName,
3817
- pathTemplate,
3818
- params: paramsMeta,
3819
- query: queryKeys
3820
- });
3904
+ const routeNameMap = /* @__PURE__ */ new Map();
3905
+ const routePathMap = /* @__PURE__ */ new Map();
3906
+ const routeMetaEntries = [];
3907
+ for (const r of router.getRoutes()) {
3908
+ const componentInfo = await getComponentInfoFromRouteRecord(r, { rootDir: cwd });
3909
+ const componentName = resolveIntrospectedComponentName(componentInfo, options.componentNaming);
3910
+ if (!componentName)
3911
+ continue;
3912
+ if (typeof r.path === "string" && r.path.length) {
3913
+ routePathMap.set(r.path, componentName);
3914
+ }
3915
+ if (typeof r.name === "string" && r.name.length) {
3916
+ const key = toPascalCase(r.name);
3917
+ routeNameMap.set(key, componentName);
3918
+ }
3919
+ const { paramKeys, queryKeys } = getRoutePropsKeys(r);
3920
+ const paramsMeta = getRouteParamMeta(router, r, paramKeys);
3921
+ const pathTemplate = buildRouteTemplate(router, r, paramsMeta.map((p) => p.name));
3922
+ if (typeof pathTemplate === "string" && pathTemplate.length) {
3923
+ routeMetaEntries.push({
3924
+ componentName,
3925
+ pathTemplate,
3926
+ params: paramsMeta,
3927
+ query: queryKeys
3928
+ });
3929
+ }
3821
3930
  }
3931
+ return { routeNameMap, routePathMap, routeMetaEntries };
3932
+ } finally {
3933
+ debugLog("closing internal vite server");
3934
+ await server.close();
3822
3935
  }
3823
- return { routeNameMap, routePathMap, routeMetaEntries };
3824
3936
  } finally {
3825
- debugLog("closing internal vite server");
3826
- await server.close();
3937
+ restoreDomShim();
3827
3938
  }
3828
3939
  });
3829
3940
  }
@@ -7997,6 +8108,13 @@ function tryCreateElementMetadata(args) {
7997
8108
  };
7998
8109
  return metadata;
7999
8110
  }
8111
+ function resolveCompilerSfcParse(compilerSfc2) {
8112
+ const parse = compilerSfc2.parse ?? compilerSfc2.default?.parse;
8113
+ if (typeof parse !== "function") {
8114
+ throw new TypeError("[vue-pom-generator] Failed to resolve @vue/compiler-sfc.parse.");
8115
+ }
8116
+ return parse;
8117
+ }
8000
8118
  function extractMetadataAfterTransform(ast, componentName, elementMetadata, semanticNameMap, testIdAttribute) {
8001
8119
  const componentMetadata = /* @__PURE__ */ new Map();
8002
8120
  function traverseNode(node) {
@@ -8193,7 +8311,8 @@ function createVuePluginWithTestIds(options) {
8193
8311
  }
8194
8312
  const componentName = getComponentNameFromPath(cleanPath);
8195
8313
  loggerRef.current.debug(`Collecting metadata for ${cleanPath} (component: ${componentName})`);
8196
- const { parse } = await import("@vue/compiler-sfc");
8314
+ const compilerSfc2 = await import("@vue/compiler-sfc");
8315
+ const parse = resolveCompilerSfcParse(compilerSfc2);
8197
8316
  const compilerDom2 = await import("@vue/compiler-dom");
8198
8317
  const compile = compilerDom2.compile;
8199
8318
  const { descriptor } = parse(code, { filename: cleanPath });