@immense/vue-pom-generator 1.0.39 → 1.0.41

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,40 +1,41 @@
1
- ● # Release Notes: v1.0.39
1
+ ● # Release Notes - v1.0.41
2
2
 
3
3
  ## Highlights
4
4
 
5
- - **Flattened helper attachments**: New capability in class generation for handling helper
6
- attachments in a flattened structure
7
- - **Extensive documentation updates**: README expanded with over 1,100 new lines of
8
- documentation
9
- - **Enhanced test coverage**: Added 89 lines of new tests for generated TypeScript compilation
10
- - **PR automation**: Added release notes preview comments on pull requests
5
+ - Fixed keyed click test ID scoping to prevent conflicts
6
+ - Aligned attachment scopes for consistent behavior
7
+ - Aligned dev snapshot options across plugin configurations
8
+ - Added PR release notes preview comments via GitHub Actions
9
+ - Expanded test coverage with new dev plugin options tests
11
10
 
12
11
  ## Changes
13
12
 
14
- ### Features
15
- - Add flattened helper attachments support in class generation (`class-generation/index.ts`)
13
+ **Bug Fixes**
14
+ - Fixed keyed click test ID scoping issues
15
+ - Aligned attachment scopes for proper C# navigation returns
16
+ - Aligned dev snapshot options across build and dev plugins
16
17
 
17
- ### Documentation
18
- - Significantly expanded README with detailed documentation (+1,118 lines)
18
+ **Tooling & CI**
19
+ - Updated release workflow to use npm 11.5.1 via npx
20
+ - Added automated PR release notes preview comments
19
21
 
20
- ### Testing
21
- - Enhanced `tests/generated-tsc.test.ts` with additional test cases (+89 lines)
22
+ **Testing**
23
+ - Added comprehensive dev plugin options test suite (`tests/dev-plugin-options.test.ts`)
24
+ - Expanded transform tests with additional coverage
22
25
 
23
- ### Tooling
24
- - Added PR release-notes preview comment automation
25
- - Minor updates to plugin type definitions and support files
26
-
27
- ## Breaking Changes
28
-
29
- None
26
+ **Internal**
27
+ - Updated utility functions for improved scoping logic
28
+ - Refined plugin configuration handling
30
29
 
31
30
  ## Pull Requests Included
32
31
 
33
- - #1 Add PR release-notes preview comments (https://github.com/immense/vue-pom-generator/pull/1)
34
- by @dkattan
32
+ - [#4 Fix keyed POM dedupe and C# navigation
33
+ returns](https://github.com/immense/vue-pom-generator/pull/4) (@dkattan)
34
+ - [#1 Add PR release-notes preview
35
+ comments](https://github.com/immense/vue-pom-generator/pull/1) (@dkattan)
35
36
 
36
37
  ## Testing
37
38
 
38
- Tests updated and expanded to cover new flattened helper attachments functionality. Added 89
39
- lines of test coverage in `tests/generated-tsc.test.ts`.
39
+ Added 160+ lines of new tests for dev plugin options. Existing transform tests expanded with
40
+ additional assertions.
40
41
 
@@ -75,7 +75,7 @@ interface CustomPomAttachment {
75
75
  className: string;
76
76
  propertyName: string;
77
77
  attachWhenUsesComponents: string[];
78
- attachTo?: "views" | "components" | "both";
78
+ attachTo?: "views" | "components" | "both" | "pagesAndComponents";
79
79
  flatten?: boolean;
80
80
  }
81
81
 
@@ -855,6 +855,7 @@ function generateAggregatedCSharpFiles(
855
855
  chunks.push(" {");
856
856
  if (pom.formattedDataTestId.includes("${") || allTestIds.length <= 1) {
857
857
  chunks.push(` await ${locatorName}${pom.formattedDataTestId.includes("${") ? `(${args})` : ""}.ClickAsync();`);
858
+ chunks.push(` return new ${target}(Page);`);
858
859
  }
859
860
  else {
860
861
  chunks.push(" Exception? lastError = null;");
@@ -876,7 +877,6 @@ function generateAggregatedCSharpFiles(
876
877
  chunks.push(" }");
877
878
  chunks.push(" throw lastError ?? new System.Exception(\"[pom] Failed to navigate using any candidate test id.\");");
878
879
  }
879
- chunks.push(` return new ${target}(Page);`);
880
880
  chunks.push(" }");
881
881
  chunks.push("");
882
882
  continue;
@@ -8,7 +8,7 @@ interface CustomPomAttachment {
8
8
  className: string;
9
9
  propertyName: string;
10
10
  attachWhenUsesComponents: string[];
11
- attachTo?: "views" | "components" | "both";
11
+ attachTo?: "views" | "components" | "both" | "pagesAndComponents";
12
12
  flatten?: boolean;
13
13
  }
14
14
  export interface GenerateFilesOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../class-generation/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,sBAAsB,EAAoE,MAAM,UAAU,CAAC;AAQpH,OAAO,EAAE,oCAAoC,EAAE,CAAC;AA8ChD,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AASD,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA8PD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAE1D;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,oCAAoC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAEzD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAE7C,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,aAAa,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAEvC,6BAA6B;IAC7B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF,6EAA6E;IAC7E,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mDAAmD;IACnD,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAEnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClD;AA+BD,wBAAsB,aAAa,CACjC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAC1D,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,iBAAiB,EAAE,MAAM,EACzB,OAAO,GAAE,oBAAyB,iBAmFnC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../class-generation/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAAE,sBAAsB,EAAoE,MAAM,UAAU,CAAC;AAQpH,OAAO,EAAE,oCAAoC,EAAE,CAAC;AA8ChD,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AASD,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,GAAG,oBAAoB,CAAC;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA8PD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;;;;;OAeG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAE1D;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,oCAAoC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAEzD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAE7C,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,aAAa,CAAC,EAAE,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;IAEvC,6BAA6B;IAC7B,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEF,6EAA6E;IAC7E,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,2FAA2F;IAC3F,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mDAAmD;IACnD,UAAU,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAEnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClD;AA+BD,wBAAsB,aAAa,CACjC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAC1D,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,iBAAiB,EAAE,MAAM,EACzB,OAAO,GAAE,oBAAyB,iBAmFnC"}
package/dist/index.cjs CHANGED
@@ -739,14 +739,16 @@ function nodeHasForDirective(node) {
739
739
  function getKeyDirective(node) {
740
740
  return findDirectiveByName(node, "bind", "key") ?? null;
741
741
  }
742
- function getKeyDirectiveValue(node, context = null) {
742
+ function getKeyDirectiveValue(node, _context = null) {
743
743
  const keyDirective = getKeyDirective(node);
744
- let value = keyDirective?.exp?.loc.source;
745
- if (value) {
746
- if (context) {
747
- value = compilerCore.stringifyExpression(keyDirective.exp);
748
- }
749
- return `\${${value}}`;
744
+ const rawSource = keyDirective?.exp?.loc.source?.trim();
745
+ if (rawSource) {
746
+ return `\${${rawSource}}`;
747
+ }
748
+ if (keyDirective?.exp) {
749
+ const value = compilerCore.stringifyExpression(keyDirective.exp);
750
+ if (value)
751
+ return `\${${value}}`;
750
752
  }
751
753
  return null;
752
754
  }
@@ -2095,9 +2097,6 @@ Fix: either (1) include ${args.bestKeyPlaceholder} in your :${attrLabel} templat
2095
2097
  })();
2096
2098
  const tryMergeWithExistingPrimary = (candidateActionName) => {
2097
2099
  const mergeKey = (args.pomMergeKey ?? "").trim();
2098
- if (isKeyed) {
2099
- return false;
2100
- }
2101
2100
  const existingEntry = primaryByActionName.get(candidateActionName);
2102
2101
  const existingPom = existingEntry?.pom;
2103
2102
  if (!existingEntry || !existingPom) {
@@ -2108,6 +2107,9 @@ Fix: either (1) include ${args.bestKeyPlaceholder} in your :${attrLabel} templat
2108
2107
  ...existingPom.alternateFormattedDataTestIds ?? []
2109
2108
  ];
2110
2109
  const sharesSelectorIdentity = existingSelectors.includes(formattedDataTestIdForPom);
2110
+ if (isKeyed && !sharesSelectorIdentity) {
2111
+ return false;
2112
+ }
2111
2113
  if (!mergeKey && !sharesSelectorIdentity) {
2112
2114
  return false;
2113
2115
  }
@@ -2154,6 +2156,11 @@ Fix: either (1) include ${args.bestKeyPlaceholder} in your :${attrLabel} templat
2154
2156
  conflicts = false;
2155
2157
  }
2156
2158
  }
2159
+ if (conflicts && nameCollisionBehavior === "error" && tryMergeWithExistingPrimary(actionName)) {
2160
+ methodName = candidate;
2161
+ mergedIntoExisting = true;
2162
+ break;
2163
+ }
2157
2164
  if (conflicts && nameCollisionBehavior === "error") {
2158
2165
  const roleSuffix = upperFirst(normalizedRole || "Element");
2159
2166
  const baseNameUpper = upperFirst(baseWithSuffix);
@@ -2200,11 +2207,6 @@ Fix: either (1) include ${args.bestKeyPlaceholder} in your :${attrLabel} templat
2200
2207
  reservedMembers.add(actionName);
2201
2208
  break;
2202
2209
  }
2203
- if (nameCollisionBehavior === "error" && tryMergeWithExistingPrimary(actionName)) {
2204
- methodName = candidate;
2205
- mergedIntoExisting = true;
2206
- break;
2207
- }
2208
2210
  if (!collisionDetails) {
2209
2211
  collisionDetails = { getterName: chosenGetterName, actionName };
2210
2212
  collisionHint = hint || (args.semanticNameHint ?? "").trim() || null;
@@ -3781,6 +3783,7 @@ function generateAggregatedCSharpFiles(componentHierarchyMap, outDir, options =
3781
3783
  chunks.push(" {");
3782
3784
  if (pom.formattedDataTestId.includes("${") || allTestIds.length <= 1) {
3783
3785
  chunks.push(` await ${locatorName}${pom.formattedDataTestId.includes("${") ? `(${args})` : ""}.ClickAsync();`);
3786
+ chunks.push(` return new ${target}(Page);`);
3784
3787
  } else {
3785
3788
  chunks.push(" Exception? lastError = null;");
3786
3789
  chunks.push(` foreach (var testId in new[] { ${allTestIds.map(toCSharpTestIdExpression).join(", ")} })`);
@@ -3801,7 +3804,6 @@ function generateAggregatedCSharpFiles(componentHierarchyMap, outDir, options =
3801
3804
  chunks.push(" }");
3802
3805
  chunks.push(' throw lastError ?? new System.Exception("[pom] Failed to navigate using any candidate test id.");');
3803
3806
  }
3804
- chunks.push(` return new ${target}(Page);`);
3805
3807
  chunks.push(" }");
3806
3808
  chunks.push("");
3807
3809
  continue;
@@ -6008,6 +6010,7 @@ function createDevProcessorPlugin(options) {
6008
6010
  customPomDir,
6009
6011
  customPomImportAliases,
6010
6012
  customPomImportNameCollisionBehavior,
6013
+ nameCollisionBehavior = "suffix",
6011
6014
  testIdAttribute,
6012
6015
  routerAwarePoms,
6013
6016
  resolvedRouterEntry,
@@ -6155,7 +6158,14 @@ function createDevProcessorPlugin(options) {
6155
6158
  nativeWrappers,
6156
6159
  excludedComponents,
6157
6160
  getViewsDirAbs(),
6158
- { existingIdBehavior: "preserve", testIdAttribute, wrapperSearchRoots: getWrapperSearchRoots() }
6161
+ {
6162
+ existingIdBehavior: "preserve",
6163
+ nameCollisionBehavior,
6164
+ testIdAttribute,
6165
+ warn: (message) => loggerRef.current.warn(message),
6166
+ vueFilesPathMap: snapshotVuePathMap,
6167
+ wrapperSearchRoots: getWrapperSearchRoots()
6168
+ }
6159
6169
  )
6160
6170
  ]
6161
6171
  });
@@ -6198,6 +6208,8 @@ function createDevProcessorPlugin(options) {
6198
6208
  customPomDir,
6199
6209
  customPomImportAliases,
6200
6210
  customPomImportNameCollisionBehavior,
6211
+ viewsDir,
6212
+ scanDirs,
6201
6213
  testIdAttribute,
6202
6214
  vueRouterFluentChaining: routerAwarePoms,
6203
6215
  routerEntry: resolvedRouterEntry,
@@ -6381,6 +6393,7 @@ function createSupportPlugins(options) {
6381
6393
  viewsDir,
6382
6394
  scanDirs,
6383
6395
  getWrapperSearchRoots,
6396
+ nameCollisionBehavior = "suffix",
6384
6397
  outDir,
6385
6398
  emitLanguages,
6386
6399
  csharp,
@@ -6457,6 +6470,7 @@ function createSupportPlugins(options) {
6457
6470
  customPomDir,
6458
6471
  customPomImportAliases,
6459
6472
  customPomImportNameCollisionBehavior,
6473
+ nameCollisionBehavior,
6460
6474
  testIdAttribute,
6461
6475
  routerAwarePoms,
6462
6476
  routerType,
@@ -7037,6 +7051,7 @@ function createVuePomGeneratorPlugins(options = {}) {
7037
7051
  viewsDir,
7038
7052
  scanDirs,
7039
7053
  getWrapperSearchRoots: getWrapperSearchRootsAbs,
7054
+ nameCollisionBehavior,
7040
7055
  outDir,
7041
7056
  emitLanguages,
7042
7057
  csharp,