@immense/vue-pom-generator 1.0.64 → 1.0.66
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 +14 -35
- package/class-generation/index.ts +7 -4
- package/dist/index.cjs +43 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +43 -19
- package/dist/index.mjs.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,48 +1,27 @@
|
|
|
1
|
-
●
|
|
1
|
+
● ## Highlights
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# v1.0.64
|
|
6
|
-
|
|
7
|
-
## Highlights
|
|
8
|
-
|
|
9
|
-
- **TypeScript template expression support** – Compiler now parses TypeScript annotations in Vue
|
|
10
|
-
template expressions (e.g., `@row-click="(row: RowType) => ..."`), fixing crashes in Nuxt 4 +
|
|
11
|
-
TS codebases
|
|
12
|
-
- **Graceful submit-button fallback** – Submit buttons with dynamic labels now respect
|
|
13
|
-
`missingSemanticNameBehavior: "ignore"` and generate `SubmitButton` / `clickSubmit()` methods
|
|
14
|
-
instead of throwing
|
|
15
|
-
- **Improved TypeScript compatibility** – All three plugin compilation paths (dev-plugin,
|
|
16
|
-
build-plugin, vue-plugin) now support TypeScript expression syntax
|
|
3
|
+
- Fixed component child POM attachment bug
|
|
4
|
+
- Added comprehensive test coverage for class generation
|
|
17
5
|
|
|
18
6
|
## Changes
|
|
19
7
|
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
**Bug Fixes**
|
|
9
|
+
- Corrected logic for attaching child page object models to component classes
|
|
10
|
+
- Improved reliability of generated POM hierarchies
|
|
11
|
+
|
|
12
|
+
**Testing**
|
|
13
|
+
- Added 53 lines of test coverage for class generation scenarios
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
- Submit buttons with dynamic inner text (e.g., ternary expressions like `{{ isNew ? 'Create' :
|
|
28
|
-
'Save' }}`) now honor `missingSemanticNameBehavior: "ignore"` option
|
|
29
|
-
- Falls back to literal `"submit"` identifier when semantic name cannot be derived, generating
|
|
30
|
-
`SubmitButton` / `clickSubmit()` POM surface
|
|
31
|
-
- Default behavior (throwing on missing semantic name) remains unchanged
|
|
15
|
+
## Breaking Changes
|
|
32
16
|
|
|
33
|
-
|
|
34
|
-
- Added 3 regression tests for TypeScript expression parsing and submit-button fallback behavior
|
|
35
|
-
- Test suite: 163 → 166 tests passing
|
|
36
|
-
- All validation passes: typecheck, eslint, build
|
|
17
|
+
None
|
|
37
18
|
|
|
38
19
|
## Pull Requests Included
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
[#20](https://github.com/immense/vue-pom-generator/pull/20)
|
|
21
|
+
Unable to determine specific PR for commit `e1f328c` from available metadata.
|
|
42
22
|
|
|
43
23
|
## Testing
|
|
44
24
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
tests).
|
|
25
|
+
Added new test cases in `tests/class-generation-coverage.test.ts` covering component child POM
|
|
26
|
+
attachment scenarios.
|
|
48
27
|
|
|
@@ -1710,9 +1710,9 @@ function prepareViewObjectModelClass(
|
|
|
1710
1710
|
members.push(...getComponentInstances(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass, widgetInstances));
|
|
1711
1711
|
members.push(getConstructor(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass, widgetInstances, { testIdAttribute }));
|
|
1712
1712
|
}
|
|
1713
|
-
if (!isView && attachmentsForThisClass.length > 0) {
|
|
1714
|
-
members.push(...getComponentInstances(
|
|
1715
|
-
members.push(getConstructor(
|
|
1713
|
+
if (!isView && (componentRefsForInstances.size > 0 || attachmentsForThisClass.length > 0)) {
|
|
1714
|
+
members.push(...getComponentInstances(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass));
|
|
1715
|
+
members.push(getConstructor(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass, [], { testIdAttribute }));
|
|
1716
1716
|
}
|
|
1717
1717
|
|
|
1718
1718
|
members.push(
|
|
@@ -1771,7 +1771,10 @@ function generateViewObjectModelContent(
|
|
|
1771
1771
|
const basePageImport = path.relative(fromAbs, toAbs).replace(/\\/g, "/");
|
|
1772
1772
|
const basePageImportNoExt = stripExtension(basePageImport).replace(/\\/g, "/");
|
|
1773
1773
|
const basePageImportSpecifier = basePageImportNoExt.startsWith(".") ? basePageImportNoExt : `./${basePageImportNoExt}`;
|
|
1774
|
-
const needsPlaywrightPageImport = prepared.isView
|
|
1774
|
+
const needsPlaywrightPageImport = prepared.isView
|
|
1775
|
+
|| prepared.attachmentsForThisClass.length > 0
|
|
1776
|
+
|| prepared.componentRefsForInstances.size > 0
|
|
1777
|
+
|| prepared.widgetInstances.length > 0;
|
|
1775
1778
|
const customPomImportSpecifiersByClass = options.customPomImportSpecifiersByClass ?? {};
|
|
1776
1779
|
|
|
1777
1780
|
const customImports = Array.from(
|
package/dist/index.cjs
CHANGED
|
@@ -1895,6 +1895,12 @@ function nodeHandlerAttributeInfo(node) {
|
|
|
1895
1895
|
const n = node2;
|
|
1896
1896
|
return typeof n.computed === "boolean" && typeof n.key === "object" && n.key !== null && typeof n.value === "object" && n.value !== null;
|
|
1897
1897
|
};
|
|
1898
|
+
const isLogicalExpressionNode = (node2) => {
|
|
1899
|
+
if (!isNodeType2(node2, "LogicalExpression"))
|
|
1900
|
+
return false;
|
|
1901
|
+
const n = node2;
|
|
1902
|
+
return typeof n.operator === "string" && typeof n.left === "object" && n.left !== null && typeof n.right === "object" && n.right !== null;
|
|
1903
|
+
};
|
|
1898
1904
|
const getLastIdentifierFromMemberChain = (node2) => {
|
|
1899
1905
|
if (!node2)
|
|
1900
1906
|
return null;
|
|
@@ -2065,48 +2071,66 @@ function nodeHandlerAttributeInfo(node) {
|
|
|
2065
2071
|
const semanticNameHint2 = suffix ? `${toPascalCase(name)}${suffix}` : toPascalCase(name);
|
|
2066
2072
|
return semanticNameHint2;
|
|
2067
2073
|
};
|
|
2074
|
+
const unwrapSemanticHelperCall = (candidateExpr) => {
|
|
2075
|
+
if (!isCallExpressionNode(candidateExpr)) {
|
|
2076
|
+
return null;
|
|
2077
|
+
}
|
|
2078
|
+
const calleeName = getLastIdentifierFromMemberChain(candidateExpr.callee);
|
|
2079
|
+
if (calleeName !== "_unref" && calleeName !== "unref" && calleeName !== "_withModifiers" && calleeName !== "withModifiers") {
|
|
2080
|
+
return null;
|
|
2081
|
+
}
|
|
2082
|
+
const firstArg = candidateExpr.arguments[0];
|
|
2083
|
+
return typeof firstArg === "object" && firstArg !== null ? firstArg : null;
|
|
2084
|
+
};
|
|
2068
2085
|
const resolveSemanticName = (candidateExpr) => {
|
|
2069
2086
|
if (!candidateExpr) {
|
|
2070
2087
|
return null;
|
|
2071
2088
|
}
|
|
2089
|
+
const unwrappedHelperCandidate = unwrapSemanticHelperCall(candidateExpr);
|
|
2090
|
+
if (unwrappedHelperCandidate) {
|
|
2091
|
+
return resolveSemanticName(unwrappedHelperCandidate);
|
|
2092
|
+
}
|
|
2072
2093
|
const direct = getLastIdentifierFromMemberChain(candidateExpr);
|
|
2073
2094
|
if (direct) {
|
|
2074
2095
|
return toPascalCase(direct);
|
|
2075
2096
|
}
|
|
2097
|
+
const directCall = tryFromCallExpression(candidateExpr);
|
|
2098
|
+
if (directCall) {
|
|
2099
|
+
return directCall;
|
|
2100
|
+
}
|
|
2101
|
+
if (isAssignmentExpressionNode(candidateExpr)) {
|
|
2102
|
+
const lhs = getAssignmentTargetName(candidateExpr.left);
|
|
2103
|
+
if (lhs) {
|
|
2104
|
+
const rhs = stableWordFromValue(candidateExpr.right);
|
|
2105
|
+
return `Set${toPascalCase(lhs)}${rhs ?? ""}`;
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
if (isLogicalExpressionNode(candidateExpr) && candidateExpr.operator === "&&") {
|
|
2109
|
+
return resolveSemanticName(candidateExpr.right);
|
|
2110
|
+
}
|
|
2076
2111
|
if (isArrowFunctionExpressionNode(candidateExpr)) {
|
|
2077
2112
|
const body = candidateExpr.body;
|
|
2078
|
-
const directCall = tryFromCallExpression(body);
|
|
2079
|
-
if (directCall) {
|
|
2080
|
-
return directCall;
|
|
2081
|
-
}
|
|
2082
|
-
if (isAssignmentExpressionNode(body)) {
|
|
2083
|
-
const lhs = getAssignmentTargetName(body.left);
|
|
2084
|
-
if (lhs) {
|
|
2085
|
-
const rhs = stableWordFromValue(body.right);
|
|
2086
|
-
return `Set${toPascalCase(lhs)}${rhs ?? ""}`;
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
2113
|
if (isBlockStatementNode(body)) {
|
|
2090
2114
|
const stmts = body.body ?? [];
|
|
2091
2115
|
if (stmts.length > 0) {
|
|
2092
2116
|
const firstStmt = stmts[0];
|
|
2093
2117
|
if (isReturnStatementNode(firstStmt)) {
|
|
2094
|
-
const fromReturn =
|
|
2118
|
+
const fromReturn = resolveSemanticName(firstStmt.argument ?? null);
|
|
2095
2119
|
if (fromReturn) {
|
|
2096
2120
|
return fromReturn;
|
|
2097
2121
|
}
|
|
2098
2122
|
}
|
|
2099
2123
|
if (isExpressionStatementNode(firstStmt)) {
|
|
2100
|
-
const fromExpr =
|
|
2124
|
+
const fromExpr = resolveSemanticName(firstStmt.expression ?? null);
|
|
2101
2125
|
if (fromExpr) {
|
|
2102
2126
|
return fromExpr;
|
|
2103
2127
|
}
|
|
2104
2128
|
}
|
|
2105
2129
|
}
|
|
2106
2130
|
}
|
|
2107
|
-
const bodyName =
|
|
2131
|
+
const bodyName = resolveSemanticName(body);
|
|
2108
2132
|
if (bodyName) {
|
|
2109
|
-
return
|
|
2133
|
+
return bodyName;
|
|
2110
2134
|
}
|
|
2111
2135
|
}
|
|
2112
2136
|
return null;
|
|
@@ -5577,9 +5601,9 @@ function prepareViewObjectModelClass(componentName, dependencies, componentHiera
|
|
|
5577
5601
|
members.push(...getComponentInstances(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass, widgetInstances));
|
|
5578
5602
|
members.push(getConstructor(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass, widgetInstances, { testIdAttribute }));
|
|
5579
5603
|
}
|
|
5580
|
-
if (!isView && attachmentsForThisClass.length > 0) {
|
|
5581
|
-
members.push(...getComponentInstances(
|
|
5582
|
-
members.push(getConstructor(
|
|
5604
|
+
if (!isView && (componentRefsForInstances.size > 0 || attachmentsForThisClass.length > 0)) {
|
|
5605
|
+
members.push(...getComponentInstances(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass));
|
|
5606
|
+
members.push(getConstructor(componentRefsForInstances, componentHierarchyMap, attachmentsForThisClass, [], { testIdAttribute }));
|
|
5583
5607
|
}
|
|
5584
5608
|
members.push(
|
|
5585
5609
|
...getAttachmentPassthroughMethods(componentName, dependencies, attachmentsForThisClass, reservedAttachmentPassthroughNames)
|
|
@@ -5623,7 +5647,7 @@ function generateViewObjectModelContent(componentName, dependencies, componentHi
|
|
|
5623
5647
|
const basePageImport = path.relative(fromAbs, toAbs).replace(/\\/g, "/");
|
|
5624
5648
|
const basePageImportNoExt = stripExtension(basePageImport).replace(/\\/g, "/");
|
|
5625
5649
|
const basePageImportSpecifier = basePageImportNoExt.startsWith(".") ? basePageImportNoExt : `./${basePageImportNoExt}`;
|
|
5626
|
-
const needsPlaywrightPageImport = prepared.isView || prepared.attachmentsForThisClass.length > 0;
|
|
5650
|
+
const needsPlaywrightPageImport = prepared.isView || prepared.attachmentsForThisClass.length > 0 || prepared.componentRefsForInstances.size > 0 || prepared.widgetInstances.length > 0;
|
|
5627
5651
|
const customPomImportSpecifiersByClass = options.customPomImportSpecifiersByClass ?? {};
|
|
5628
5652
|
const customImports = Array.from(
|
|
5629
5653
|
/* @__PURE__ */ new Set([
|