@immense/vue-pom-generator 1.0.26 → 1.0.28
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 +22 -14
- package/dist/index.cjs +118 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +118 -6
- package/dist/index.mjs.map +1 -1
- package/dist/transform.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
●
|
|
1
|
+
● # v1.0.28
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
-
|
|
3
|
+
## Highlights
|
|
4
|
+
|
|
5
|
+
- Fixed test ID generation to preserve simple member-expression patterns (e.g.,
|
|
6
|
+
`this.someProperty`)
|
|
7
|
+
- Added automated PR release notes preview comments via GitHub Actions workflow
|
|
8
|
+
- Enhanced test coverage for utility functions
|
|
6
9
|
|
|
7
10
|
## Changes
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
-
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
- Preserve simple member-expression test IDs in transformed code
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
- Added
|
|
15
|
+
### CI/CD Improvements
|
|
16
|
+
- Added dual-strategy release notes generation via PR comments
|
|
17
|
+
- Copilot SDK-based workflow with comment upsert
|
|
18
|
+
- Copilot agentic workflow via gh-aw
|
|
19
|
+
- Release notes preview now posted automatically on PRs
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
- Added
|
|
21
|
+
### Testing
|
|
22
|
+
- Added 24+ test cases in `transform.test.ts`
|
|
23
|
+
- Added 48+ test cases in `utils-coverage.test.ts` for utility function coverage
|
|
24
|
+
- Enhanced validation of member-expression handling
|
|
17
25
|
|
|
18
26
|
## Breaking Changes
|
|
19
27
|
|
|
@@ -21,11 +29,11 @@
|
|
|
21
29
|
|
|
22
30
|
## Pull Requests Included
|
|
23
31
|
|
|
24
|
-
- #1
|
|
25
|
-
comments
|
|
32
|
+
- [#1](https://github.com/immense/vue-pom-generator/pull/1) Add PR release-notes preview
|
|
33
|
+
comments (@dkattan)
|
|
26
34
|
|
|
27
35
|
## Testing
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
Comprehensive test coverage added for the member-expression fix with 72+ new test cases across
|
|
38
|
+
transform and utility modules.
|
|
31
39
|
|
package/dist/index.cjs
CHANGED
|
@@ -1429,6 +1429,25 @@ function extractMemberPropertyName(member) {
|
|
|
1429
1429
|
}
|
|
1430
1430
|
return "";
|
|
1431
1431
|
}
|
|
1432
|
+
function isCompilerGeneratedReferenceRoot(name) {
|
|
1433
|
+
return name.startsWith("_") || name.startsWith("$");
|
|
1434
|
+
}
|
|
1435
|
+
function tryGetPreservableDynamicReferenceExpression(node) {
|
|
1436
|
+
if (!node || typeof node !== "object") {
|
|
1437
|
+
return null;
|
|
1438
|
+
}
|
|
1439
|
+
if (types.isIdentifier(node)) {
|
|
1440
|
+
return isCompilerGeneratedReferenceRoot(node.name) ? null : node.name;
|
|
1441
|
+
}
|
|
1442
|
+
if (!types.isMemberExpression(node) || node.computed) {
|
|
1443
|
+
return null;
|
|
1444
|
+
}
|
|
1445
|
+
const objectExpression = tryGetPreservableDynamicReferenceExpression(node.object);
|
|
1446
|
+
if (!objectExpression || !types.isIdentifier(node.property)) {
|
|
1447
|
+
return null;
|
|
1448
|
+
}
|
|
1449
|
+
return `${objectExpression}.${node.property.name}`;
|
|
1450
|
+
}
|
|
1432
1451
|
function normalizeHandlerName(name) {
|
|
1433
1452
|
if (!name) {
|
|
1434
1453
|
return "";
|
|
@@ -1531,6 +1550,17 @@ function tryGetExistingElementDataTestId(node, attributeName = "data-testid") {
|
|
|
1531
1550
|
}
|
|
1532
1551
|
return { value, isDynamic: false, isStaticLiteral: true };
|
|
1533
1552
|
}
|
|
1553
|
+
const preservableReference = tryGetPreservableDynamicReferenceExpression(ast);
|
|
1554
|
+
if (preservableReference) {
|
|
1555
|
+
return {
|
|
1556
|
+
value: preservableReference,
|
|
1557
|
+
isDynamic: true,
|
|
1558
|
+
isStaticLiteral: false,
|
|
1559
|
+
template: `\${${preservableReference}}`,
|
|
1560
|
+
templateExpressionCount: 1,
|
|
1561
|
+
rawExpression: preservableReference
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1534
1564
|
const raw = (simpleExp.content ?? "").trim();
|
|
1535
1565
|
if (!raw) {
|
|
1536
1566
|
return null;
|
|
@@ -1558,6 +1588,17 @@ function tryGetExistingElementDataTestId(node, attributeName = "data-testid") {
|
|
|
1558
1588
|
const sl = ast2;
|
|
1559
1589
|
return { value: sl.value ?? "", isDynamic: false, isStaticLiteral: true };
|
|
1560
1590
|
}
|
|
1591
|
+
const preservableReference2 = tryGetPreservableDynamicReferenceExpression(ast2);
|
|
1592
|
+
if (preservableReference2) {
|
|
1593
|
+
return {
|
|
1594
|
+
value: preservableReference2,
|
|
1595
|
+
isDynamic: true,
|
|
1596
|
+
isStaticLiteral: false,
|
|
1597
|
+
template: `\${${preservableReference2}}`,
|
|
1598
|
+
templateExpressionCount: 1,
|
|
1599
|
+
rawExpression: preservableReference2
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1561
1602
|
} catch {
|
|
1562
1603
|
}
|
|
1563
1604
|
return { value: raw, isDynamic: true, isStaticLiteral: false, rawExpression: raw };
|
|
@@ -1863,9 +1904,6 @@ Fix: either (1) include ${args.bestKeyPlaceholder} in your :${attrLabel} templat
|
|
|
1863
1904
|
})();
|
|
1864
1905
|
const tryMergeWithExistingPrimary = (candidateActionName) => {
|
|
1865
1906
|
const mergeKey = (args.pomMergeKey ?? "").trim();
|
|
1866
|
-
if (!mergeKey) {
|
|
1867
|
-
return false;
|
|
1868
|
-
}
|
|
1869
1907
|
if (isKeyed) {
|
|
1870
1908
|
return false;
|
|
1871
1909
|
}
|
|
@@ -1874,7 +1912,15 @@ Fix: either (1) include ${args.bestKeyPlaceholder} in your :${attrLabel} templat
|
|
|
1874
1912
|
if (!existingEntry || !existingPom) {
|
|
1875
1913
|
return false;
|
|
1876
1914
|
}
|
|
1877
|
-
|
|
1915
|
+
const existingSelectors = [
|
|
1916
|
+
existingPom.formattedDataTestId,
|
|
1917
|
+
...existingPom.alternateFormattedDataTestIds ?? []
|
|
1918
|
+
];
|
|
1919
|
+
const sharesSelectorIdentity = existingSelectors.includes(formattedDataTestIdForPom);
|
|
1920
|
+
if (!mergeKey && !sharesSelectorIdentity) {
|
|
1921
|
+
return false;
|
|
1922
|
+
}
|
|
1923
|
+
if (mergeKey && (existingPom.mergeKey ?? "").trim() !== mergeKey && !sharesSelectorIdentity) {
|
|
1878
1924
|
return false;
|
|
1879
1925
|
}
|
|
1880
1926
|
if (existingPom.nativeRole !== normalizedRole) {
|
|
@@ -4840,8 +4886,46 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
4840
4886
|
const normalizedViewsDirAbs = path.normalize(safeRealpath(path.resolve(viewsDirAbs)));
|
|
4841
4887
|
const generatedMethodContentByComponent = /* @__PURE__ */ new Map();
|
|
4842
4888
|
const lastConditionalHintByParent = /* @__PURE__ */ new WeakMap();
|
|
4889
|
+
const lastConditionalMergeGroupByParent = /* @__PURE__ */ new WeakMap();
|
|
4843
4890
|
const conditionalHintByElement = /* @__PURE__ */ new WeakMap();
|
|
4844
4891
|
const conditionalHintByIfBranch = /* @__PURE__ */ new WeakMap();
|
|
4892
|
+
const conditionalMergeGroupByElement = /* @__PURE__ */ new WeakMap();
|
|
4893
|
+
const conditionalMergeGroupByElementLoc = /* @__PURE__ */ new Map();
|
|
4894
|
+
const conditionalMergeGroupByIfBranch = /* @__PURE__ */ new WeakMap();
|
|
4895
|
+
let conditionalMergeGroupCounter = 0;
|
|
4896
|
+
const getElementLocationKey = (element) => {
|
|
4897
|
+
const startOffset = element.loc?.start.offset;
|
|
4898
|
+
const endOffset = element.loc?.end.offset;
|
|
4899
|
+
if (typeof startOffset !== "number" || typeof endOffset !== "number") {
|
|
4900
|
+
return null;
|
|
4901
|
+
}
|
|
4902
|
+
return `${element.tag}:${startOffset}:${endOffset}`;
|
|
4903
|
+
};
|
|
4904
|
+
const markConditionalMergeGroup = (nodes, mergeGroupKey) => {
|
|
4905
|
+
for (const child of nodes) {
|
|
4906
|
+
if (child.type === compilerCore.NodeTypes.ELEMENT) {
|
|
4907
|
+
const element = child;
|
|
4908
|
+
conditionalMergeGroupByElement.set(element, mergeGroupKey);
|
|
4909
|
+
const elementLocationKey = getElementLocationKey(element);
|
|
4910
|
+
if (elementLocationKey) {
|
|
4911
|
+
conditionalMergeGroupByElementLoc.set(elementLocationKey, mergeGroupKey);
|
|
4912
|
+
}
|
|
4913
|
+
markConditionalMergeGroup(element.children, mergeGroupKey);
|
|
4914
|
+
continue;
|
|
4915
|
+
}
|
|
4916
|
+
if (child.type === compilerCore.NodeTypes.IF) {
|
|
4917
|
+
const ifNode = child;
|
|
4918
|
+
for (const branch of ifNode.branches ?? []) {
|
|
4919
|
+
markConditionalMergeGroup(branch.children, mergeGroupKey);
|
|
4920
|
+
}
|
|
4921
|
+
continue;
|
|
4922
|
+
}
|
|
4923
|
+
if (child.type === compilerCore.NodeTypes.IF_BRANCH || child.type === compilerCore.NodeTypes.FOR) {
|
|
4924
|
+
const branchLike = child;
|
|
4925
|
+
markConditionalMergeGroup(branchLike.children ?? [], mergeGroupKey);
|
|
4926
|
+
}
|
|
4927
|
+
}
|
|
4928
|
+
};
|
|
4845
4929
|
return (node, context) => {
|
|
4846
4930
|
if (excludedComponents.includes(componentName)) {
|
|
4847
4931
|
return;
|
|
@@ -4849,8 +4933,15 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
4849
4933
|
if (node.type === compilerCore.NodeTypes.IF) {
|
|
4850
4934
|
const ifNode = node;
|
|
4851
4935
|
const branches = ifNode.branches ?? [];
|
|
4936
|
+
const mergeGroupKey = `if-group:${++conditionalMergeGroupCounter}`;
|
|
4937
|
+
const ifParentKey = context?.parent ? context.parent : null;
|
|
4938
|
+
if (ifParentKey) {
|
|
4939
|
+
lastConditionalMergeGroupByParent.set(ifParentKey, mergeGroupKey);
|
|
4940
|
+
}
|
|
4852
4941
|
let lastHint = null;
|
|
4853
4942
|
for (const branch of branches) {
|
|
4943
|
+
conditionalMergeGroupByIfBranch.set(branch, mergeGroupKey);
|
|
4944
|
+
markConditionalMergeGroup(branch.children ?? [], mergeGroupKey);
|
|
4854
4945
|
const cond = branch.condition ?? null;
|
|
4855
4946
|
if (!cond) {
|
|
4856
4947
|
const hint = lastHint ? `else ${lastHint}` : "else";
|
|
@@ -4929,10 +5020,28 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
4929
5020
|
const bestKeyPlaceholder = isSlotKey ? `\${${bestKeyInferred}}` : bestKeyInferred;
|
|
4930
5021
|
const bestKeyVariable = isSlotKey ? bestKeyInferred : null;
|
|
4931
5022
|
const keyValuesOverride = tryGetContainedInStaticVForSourceLiteralValues(context);
|
|
4932
|
-
const parentKey =
|
|
5023
|
+
const parentKey = context?.parent ? context.parent : null;
|
|
4933
5024
|
const conditional = getConditionalDirectiveInfo(element);
|
|
4934
5025
|
let conditionalHint = null;
|
|
5026
|
+
const elementLocationKey = getElementLocationKey(element);
|
|
5027
|
+
let conditionalMergeGroupKey = (elementLocationKey ? conditionalMergeGroupByElementLoc.get(elementLocationKey) ?? null : null) ?? conditionalMergeGroupByElement.get(element) ?? null;
|
|
5028
|
+
if (!conditionalMergeGroupKey && context?.parent?.type === compilerCore.NodeTypes.IF_BRANCH) {
|
|
5029
|
+
const branch = context.parent;
|
|
5030
|
+
conditionalMergeGroupKey = conditionalMergeGroupByIfBranch.get(branch) ?? null;
|
|
5031
|
+
}
|
|
4935
5032
|
if (conditional && (conditional.kind === "if" || conditional.kind === "else-if")) {
|
|
5033
|
+
if (parentKey) {
|
|
5034
|
+
if (!conditionalMergeGroupKey) {
|
|
5035
|
+
if (conditional.kind === "if") {
|
|
5036
|
+
conditionalMergeGroupKey = `if-group:${++conditionalMergeGroupCounter}`;
|
|
5037
|
+
} else {
|
|
5038
|
+
conditionalMergeGroupKey = lastConditionalMergeGroupByParent.get(parentKey) ?? null;
|
|
5039
|
+
}
|
|
5040
|
+
}
|
|
5041
|
+
if (conditionalMergeGroupKey) {
|
|
5042
|
+
lastConditionalMergeGroupByParent.set(parentKey, conditionalMergeGroupKey);
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
4936
5045
|
conditionalHint = tryExtractStableHintFromConditionalExpressionSource(conditional.source);
|
|
4937
5046
|
if (conditionalHint && parentKey) {
|
|
4938
5047
|
lastConditionalHintByParent.set(parentKey, conditionalHint);
|
|
@@ -4941,6 +5050,7 @@ function createTestIdTransform(componentName, componentHierarchyMap, nativeWrapp
|
|
|
4941
5050
|
if (parentKey) {
|
|
4942
5051
|
const previousHint = lastConditionalHintByParent.get(parentKey) ?? null;
|
|
4943
5052
|
conditionalHint = previousHint ? `else ${previousHint}` : null;
|
|
5053
|
+
conditionalMergeGroupKey = lastConditionalMergeGroupByParent.get(parentKey) ?? null;
|
|
4944
5054
|
}
|
|
4945
5055
|
}
|
|
4946
5056
|
if (!conditionalHint && context?.parent?.type === compilerCore.NodeTypes.IF_BRANCH) {
|
|
@@ -5048,11 +5158,13 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5048
5158
|
const nativeRole = nativeWrappers[element.tag]?.role ?? element.tag;
|
|
5049
5159
|
const primarySemanticHint = semanticNameHint || conditionalHint || void 0;
|
|
5050
5160
|
const alternates = nameCollisionBehavior === "error" && semanticNameHint && conditionalHint ? [`${semanticNameHint} ${conditionalHint}`] : void 0;
|
|
5161
|
+
const pomMergeKey = semanticNameHint && conditionalMergeGroupKey ? `wrapper:ifgroup:${conditionalMergeGroupKey}:model:${semanticNameHint}` : void 0;
|
|
5051
5162
|
applyResolvedDataTestIdForElement({
|
|
5052
5163
|
preferredGeneratedValue: nativeWrappersValue,
|
|
5053
5164
|
nativeRoleOverride: nativeRole,
|
|
5054
5165
|
semanticNameHint: primarySemanticHint,
|
|
5055
|
-
semanticNameHintAlternates: alternates
|
|
5166
|
+
semanticNameHintAlternates: alternates,
|
|
5167
|
+
pomMergeKey
|
|
5056
5168
|
});
|
|
5057
5169
|
return;
|
|
5058
5170
|
}
|