@immense/vue-pom-generator 1.0.42 → 1.0.44
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 +16 -21
- package/class-generation/Pointer.ts +43 -2
- package/class-generation/index.ts +27 -4
- package/dist/class-generation/Pointer.d.ts +2 -0
- package/dist/class-generation/Pointer.d.ts.map +1 -1
- package/dist/index.cjs +311 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +312 -149
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/create-vue-pom-generator-plugins.d.ts.map +1 -1
- package/dist/plugin/support/build-plugin.d.ts +12 -2
- package/dist/plugin/support/build-plugin.d.ts.map +1 -1
- package/dist/plugin/support/dev-plugin.d.ts +2 -0
- package/dist/plugin/support/dev-plugin.d.ts.map +1 -1
- package/dist/plugin/support-plugins.d.ts +2 -0
- package/dist/plugin/support-plugins.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +1 -1
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/tests/build-serve-parity.test.d.ts +2 -0
- package/dist/tests/build-serve-parity.test.d.ts.map +1 -0
- package/dist/tests/pointer.test.d.ts +2 -0
- package/dist/tests/pointer.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2,14 +2,14 @@ import path from "node:path";
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
4
4
|
import fs from "node:fs";
|
|
5
|
+
import * as compilerDom from "@vue/compiler-dom";
|
|
6
|
+
import { parse as parse$2 } from "@vue/compiler-dom";
|
|
7
|
+
import { parse as parse$1, compileScript } from "@vue/compiler-sfc";
|
|
5
8
|
import { parseExpression, parse } from "@babel/parser";
|
|
6
9
|
import { JSDOM } from "jsdom";
|
|
7
10
|
import { NodeTypes, stringifyExpression, ConstantTypes, createSimpleExpression } from "@vue/compiler-core";
|
|
8
11
|
import { isArrayExpression, isStringLiteral, isTemplateLiteral, isAssignmentExpression, isIdentifier, isMemberExpression, isCallExpression, isExpressionStatement, isArrowFunctionExpression, isOptionalMemberExpression, isObjectExpression, isFile, isBlockStatement, isOptionalCallExpression, isLogicalExpression, isConditionalExpression, isSequenceExpression, isAssignmentPattern, isRestElement, isObjectPattern, isObjectProperty, isProgram, VISITOR_KEYS, isBooleanLiteral, isNumericLiteral, isNullLiteral } from "@babel/types";
|
|
9
12
|
import { performance } from "node:perf_hooks";
|
|
10
|
-
import * as compilerDom from "@vue/compiler-dom";
|
|
11
|
-
import { parse as parse$2 } from "@vue/compiler-dom";
|
|
12
|
-
import { parse as parse$1 } from "@vue/compiler-sfc";
|
|
13
13
|
import virtualImport from "vite-plugin-virtual";
|
|
14
14
|
import vue from "@vitejs/plugin-vue";
|
|
15
15
|
const VUE_POM_GENERATOR_LOG_PREFIX = "[vue-pom-generator]";
|
|
@@ -3671,6 +3671,26 @@ function generateAggregatedCSharpFiles(componentHierarchyMap, outDir, options =
|
|
|
3671
3671
|
" protected IPage Page { get; }",
|
|
3672
3672
|
` protected ILocator LocatorByTestId(string testId) => Page.Locator($"[${testIdAttribute}=\\"{testId}\\"]");`,
|
|
3673
3673
|
" protected ILocator LocatorWithinTestIdByLabel(string rootTestId, string label, bool exact = true) => LocatorByTestId(rootTestId).GetByLabel(label, new() { Exact = exact });",
|
|
3674
|
+
" protected async Task<ILocator> ResolveEditableLocatorAsync(ILocator locator)",
|
|
3675
|
+
" {",
|
|
3676
|
+
' var isEditable = await locator.EvaluateAsync<bool>(@"el => {',
|
|
3677
|
+
" if (!el || !(el instanceof HTMLElement)) return false;",
|
|
3678
|
+
" const tagName = el.tagName.toLowerCase();",
|
|
3679
|
+
" return tagName === 'input' || tagName === 'textarea' || tagName === 'select' || el.isContentEditable;",
|
|
3680
|
+
' }");',
|
|
3681
|
+
" if (isEditable)",
|
|
3682
|
+
" {",
|
|
3683
|
+
" return locator;",
|
|
3684
|
+
" }",
|
|
3685
|
+
"",
|
|
3686
|
+
` var descendant = locator.Locator("input, textarea, select, [contenteditable=''], [contenteditable='true'], [contenteditable]:not([contenteditable='false'])").First;`,
|
|
3687
|
+
" if (await descendant.CountAsync() > 0)",
|
|
3688
|
+
" {",
|
|
3689
|
+
" return descendant;",
|
|
3690
|
+
" }",
|
|
3691
|
+
"",
|
|
3692
|
+
" return locator;",
|
|
3693
|
+
" }",
|
|
3674
3694
|
" protected async Task ClickWithinTestIdByLabelAsync(string rootTestId, string label, bool exact = true)",
|
|
3675
3695
|
" {",
|
|
3676
3696
|
" await LocatorWithinTestIdByLabel(rootTestId, label, exact).ClickAsync();",
|
|
@@ -3772,7 +3792,8 @@ function generateAggregatedCSharpFiles(componentHierarchyMap, outDir, options =
|
|
|
3772
3792
|
const callSuffix = pom.formattedDataTestId.includes("${") ? `(${args})` : "";
|
|
3773
3793
|
const emitActionCall = (locatorAccess) => {
|
|
3774
3794
|
if (pom.nativeRole === "input") {
|
|
3775
|
-
chunks.push(` await ${locatorAccess}
|
|
3795
|
+
chunks.push(` var editableLocator = await ResolveEditableLocatorAsync(${locatorAccess});`);
|
|
3796
|
+
chunks.push(" await editableLocator.FillAsync(text);");
|
|
3776
3797
|
} else if (pom.nativeRole === "select") {
|
|
3777
3798
|
chunks.push(` await ${locatorAccess}.SelectOptionAsync(value);`);
|
|
3778
3799
|
} else if (pom.nativeRole === "vselect") {
|
|
@@ -3800,7 +3821,8 @@ function generateAggregatedCSharpFiles(componentHierarchyMap, outDir, options =
|
|
|
3800
3821
|
chunks.push(" if (await locator.CountAsync() > 0)");
|
|
3801
3822
|
chunks.push(" {");
|
|
3802
3823
|
if (pom.nativeRole === "input") {
|
|
3803
|
-
chunks.push(" await locator
|
|
3824
|
+
chunks.push(" var editableLocator = await ResolveEditableLocatorAsync(locator);");
|
|
3825
|
+
chunks.push(" await editableLocator.FillAsync(text);");
|
|
3804
3826
|
} else if (pom.nativeRole === "select") {
|
|
3805
3827
|
chunks.push(" await locator.SelectOptionAsync(value);");
|
|
3806
3828
|
} else {
|
|
@@ -4024,7 +4046,8 @@ function generateViewObjectModelContent(componentName, dependencies, componentHi
|
|
|
4024
4046
|
if (!Object.prototype.hasOwnProperty.call(customPomClassIdentifierMap, a.className))
|
|
4025
4047
|
return false;
|
|
4026
4048
|
const scope = a.attachTo ?? "views";
|
|
4027
|
-
const
|
|
4049
|
+
const scopeMatchesBoth = scope === "both" || scope === "pagesAndComponents";
|
|
4050
|
+
const scopeOk = isView ? scope === "views" || scopeMatchesBoth : scope === "components" || scopeMatchesBoth;
|
|
4028
4051
|
if (!scopeOk)
|
|
4029
4052
|
return false;
|
|
4030
4053
|
return a.attachWhenUsesComponents.some((c) => hasChildComponent(c));
|
|
@@ -4727,148 +4750,6 @@ function getConstructor(childrenComponent, componentHierarchyMap, attachmentsFor
|
|
|
4727
4750
|
return `${content}
|
|
4728
4751
|
`;
|
|
4729
4752
|
}
|
|
4730
|
-
function summarizeHierarchyMap(componentHierarchyMap) {
|
|
4731
|
-
let interactiveComponentCount = 0;
|
|
4732
|
-
let dataTestIdCount = 0;
|
|
4733
|
-
for (const dependencies of componentHierarchyMap.values()) {
|
|
4734
|
-
const selectorCount = dependencies.dataTestIdSet?.size ?? 0;
|
|
4735
|
-
if (selectorCount > 0) {
|
|
4736
|
-
interactiveComponentCount += 1;
|
|
4737
|
-
dataTestIdCount += selectorCount;
|
|
4738
|
-
}
|
|
4739
|
-
}
|
|
4740
|
-
return {
|
|
4741
|
-
entryCount: componentHierarchyMap.size,
|
|
4742
|
-
interactiveComponentCount,
|
|
4743
|
-
dataTestIdCount
|
|
4744
|
-
};
|
|
4745
|
-
}
|
|
4746
|
-
function isLessRich(candidate, previous) {
|
|
4747
|
-
if (candidate.dataTestIdCount !== previous.dataTestIdCount) {
|
|
4748
|
-
return candidate.dataTestIdCount < previous.dataTestIdCount;
|
|
4749
|
-
}
|
|
4750
|
-
if (candidate.interactiveComponentCount !== previous.interactiveComponentCount) {
|
|
4751
|
-
return candidate.interactiveComponentCount < previous.interactiveComponentCount;
|
|
4752
|
-
}
|
|
4753
|
-
return candidate.entryCount < previous.entryCount;
|
|
4754
|
-
}
|
|
4755
|
-
function createBuildProcessorPlugin(options) {
|
|
4756
|
-
const {
|
|
4757
|
-
componentHierarchyMap,
|
|
4758
|
-
vueFilesPathMap,
|
|
4759
|
-
viewsDir,
|
|
4760
|
-
scanDirs,
|
|
4761
|
-
basePageClassPath,
|
|
4762
|
-
normalizedBasePagePath,
|
|
4763
|
-
outDir,
|
|
4764
|
-
emitLanguages,
|
|
4765
|
-
csharp,
|
|
4766
|
-
generateFixtures,
|
|
4767
|
-
customPomAttachments,
|
|
4768
|
-
projectRootRef,
|
|
4769
|
-
customPomDir,
|
|
4770
|
-
customPomImportAliases,
|
|
4771
|
-
customPomImportNameCollisionBehavior,
|
|
4772
|
-
testIdAttribute,
|
|
4773
|
-
routerAwarePoms,
|
|
4774
|
-
resolvedRouterEntry,
|
|
4775
|
-
routerType,
|
|
4776
|
-
routerModuleShims,
|
|
4777
|
-
loggerRef
|
|
4778
|
-
} = options;
|
|
4779
|
-
let lastGeneratedMetrics = {
|
|
4780
|
-
entryCount: 0,
|
|
4781
|
-
interactiveComponentCount: 0,
|
|
4782
|
-
dataTestIdCount: 0
|
|
4783
|
-
};
|
|
4784
|
-
return {
|
|
4785
|
-
name: "vue-pom-generator-build",
|
|
4786
|
-
// This plugin exists to generate code on build output; it is not needed during dev-server HMR.
|
|
4787
|
-
apply: "build",
|
|
4788
|
-
enforce: "pre",
|
|
4789
|
-
async buildStart() {
|
|
4790
|
-
if (!routerAwarePoms) {
|
|
4791
|
-
setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
|
|
4792
|
-
setResolveToComponentNameFn(() => null);
|
|
4793
|
-
return;
|
|
4794
|
-
}
|
|
4795
|
-
let result;
|
|
4796
|
-
if (routerType === "nuxt") {
|
|
4797
|
-
result = await introspectNuxtPages(projectRootRef.current);
|
|
4798
|
-
} else {
|
|
4799
|
-
if (!resolvedRouterEntry)
|
|
4800
|
-
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
4801
|
-
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
4802
|
-
moduleShims: routerModuleShims,
|
|
4803
|
-
componentNaming: {
|
|
4804
|
-
projectRoot: projectRootRef.current,
|
|
4805
|
-
viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
|
|
4806
|
-
scanDirs
|
|
4807
|
-
}
|
|
4808
|
-
});
|
|
4809
|
-
}
|
|
4810
|
-
const { routeNameMap, routePathMap } = result;
|
|
4811
|
-
setRouteNameToComponentNameMap(routeNameMap);
|
|
4812
|
-
setResolveToComponentNameFn((to) => {
|
|
4813
|
-
if (typeof to === "string") {
|
|
4814
|
-
return routePathMap.get(to) ?? null;
|
|
4815
|
-
}
|
|
4816
|
-
const maybe = to;
|
|
4817
|
-
if (typeof maybe.name === "string" && maybe.name.length) {
|
|
4818
|
-
const key = toPascalCase(maybe.name);
|
|
4819
|
-
return routeNameMap.get(key) ?? null;
|
|
4820
|
-
}
|
|
4821
|
-
if (typeof maybe.path === "string" && maybe.path.length) {
|
|
4822
|
-
return routePathMap.get(maybe.path) ?? null;
|
|
4823
|
-
}
|
|
4824
|
-
return null;
|
|
4825
|
-
});
|
|
4826
|
-
if (!fs.existsSync(basePageClassPath)) {
|
|
4827
|
-
this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
|
|
4828
|
-
}
|
|
4829
|
-
this.addWatchFile(basePageClassPath);
|
|
4830
|
-
const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
|
|
4831
|
-
if (!fs.existsSync(pointerPath)) {
|
|
4832
|
-
this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
|
|
4833
|
-
}
|
|
4834
|
-
this.addWatchFile(pointerPath);
|
|
4835
|
-
},
|
|
4836
|
-
async buildEnd(error) {
|
|
4837
|
-
if (error) {
|
|
4838
|
-
return;
|
|
4839
|
-
}
|
|
4840
|
-
const metrics = summarizeHierarchyMap(componentHierarchyMap);
|
|
4841
|
-
if (metrics.dataTestIdCount <= 0) {
|
|
4842
|
-
return;
|
|
4843
|
-
}
|
|
4844
|
-
if (isLessRich(metrics, lastGeneratedMetrics)) {
|
|
4845
|
-
return;
|
|
4846
|
-
}
|
|
4847
|
-
await generateFiles(componentHierarchyMap, vueFilesPathMap, normalizedBasePagePath, {
|
|
4848
|
-
outDir,
|
|
4849
|
-
emitLanguages,
|
|
4850
|
-
csharp,
|
|
4851
|
-
generateFixtures,
|
|
4852
|
-
customPomAttachments,
|
|
4853
|
-
projectRoot: projectRootRef.current,
|
|
4854
|
-
customPomDir,
|
|
4855
|
-
customPomImportAliases,
|
|
4856
|
-
customPomImportNameCollisionBehavior,
|
|
4857
|
-
testIdAttribute,
|
|
4858
|
-
vueRouterFluentChaining: routerAwarePoms,
|
|
4859
|
-
routerEntry: resolvedRouterEntry,
|
|
4860
|
-
routerType,
|
|
4861
|
-
viewsDir,
|
|
4862
|
-
scanDirs
|
|
4863
|
-
});
|
|
4864
|
-
lastGeneratedMetrics = metrics;
|
|
4865
|
-
loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.interactiveComponentCount} interactive components, ${metrics.dataTestIdCount} selectors)`);
|
|
4866
|
-
},
|
|
4867
|
-
closeBundle() {
|
|
4868
|
-
loggerRef.current.info("build complete");
|
|
4869
|
-
}
|
|
4870
|
-
};
|
|
4871
|
-
}
|
|
4872
4753
|
const TESTID_CLICK_EVENT_NAME = "__testid_event__";
|
|
4873
4754
|
const TESTID_CLICK_EVENT_STRICT_FLAG = "__testid_click_event_strict__";
|
|
4874
4755
|
const CLICK_EVENT_NAME = TESTID_CLICK_EVENT_NAME;
|
|
@@ -5951,6 +5832,265 @@ Fix: remove the explicit ${attrLabel}, or change existingIdBehavior to "overwrit
|
|
|
5951
5832
|
}
|
|
5952
5833
|
};
|
|
5953
5834
|
}
|
|
5835
|
+
function summarizeHierarchyMap(componentHierarchyMap) {
|
|
5836
|
+
let interactiveComponentCount = 0;
|
|
5837
|
+
let dataTestIdCount = 0;
|
|
5838
|
+
for (const dependencies of componentHierarchyMap.values()) {
|
|
5839
|
+
const selectorCount = dependencies.dataTestIdSet?.size ?? 0;
|
|
5840
|
+
if (selectorCount > 0) {
|
|
5841
|
+
interactiveComponentCount += 1;
|
|
5842
|
+
dataTestIdCount += selectorCount;
|
|
5843
|
+
}
|
|
5844
|
+
}
|
|
5845
|
+
return {
|
|
5846
|
+
entryCount: componentHierarchyMap.size,
|
|
5847
|
+
interactiveComponentCount,
|
|
5848
|
+
dataTestIdCount
|
|
5849
|
+
};
|
|
5850
|
+
}
|
|
5851
|
+
function isLessRich(candidate, previous) {
|
|
5852
|
+
if (candidate.dataTestIdCount !== previous.dataTestIdCount) {
|
|
5853
|
+
return candidate.dataTestIdCount < previous.dataTestIdCount;
|
|
5854
|
+
}
|
|
5855
|
+
if (candidate.interactiveComponentCount !== previous.interactiveComponentCount) {
|
|
5856
|
+
return candidate.interactiveComponentCount < previous.interactiveComponentCount;
|
|
5857
|
+
}
|
|
5858
|
+
return candidate.entryCount < previous.entryCount;
|
|
5859
|
+
}
|
|
5860
|
+
function createBuildProcessorPlugin(options) {
|
|
5861
|
+
const {
|
|
5862
|
+
componentHierarchyMap,
|
|
5863
|
+
vueFilesPathMap,
|
|
5864
|
+
viewsDir,
|
|
5865
|
+
scanDirs,
|
|
5866
|
+
basePageClassPath,
|
|
5867
|
+
normalizedBasePagePath,
|
|
5868
|
+
outDir,
|
|
5869
|
+
emitLanguages,
|
|
5870
|
+
csharp,
|
|
5871
|
+
generateFixtures,
|
|
5872
|
+
customPomAttachments,
|
|
5873
|
+
projectRootRef,
|
|
5874
|
+
customPomDir,
|
|
5875
|
+
customPomImportAliases,
|
|
5876
|
+
customPomImportNameCollisionBehavior,
|
|
5877
|
+
testIdAttribute,
|
|
5878
|
+
nameCollisionBehavior,
|
|
5879
|
+
existingIdBehavior,
|
|
5880
|
+
nativeWrappers,
|
|
5881
|
+
excludedComponents,
|
|
5882
|
+
getWrapperSearchRoots,
|
|
5883
|
+
routerAwarePoms,
|
|
5884
|
+
resolvedRouterEntry,
|
|
5885
|
+
routerType,
|
|
5886
|
+
routerModuleShims,
|
|
5887
|
+
loggerRef
|
|
5888
|
+
} = options;
|
|
5889
|
+
let lastGeneratedMetrics = {
|
|
5890
|
+
entryCount: 0,
|
|
5891
|
+
interactiveComponentCount: 0,
|
|
5892
|
+
dataTestIdCount: 0
|
|
5893
|
+
};
|
|
5894
|
+
const getViewsDirAbs = () => path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir);
|
|
5895
|
+
const getScriptInfo = (source, filename) => {
|
|
5896
|
+
try {
|
|
5897
|
+
const { descriptor } = parse$1(source, { filename });
|
|
5898
|
+
if (!descriptor.script && !descriptor.scriptSetup)
|
|
5899
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
5900
|
+
const scriptBlock = compileScript(descriptor, { id: filename });
|
|
5901
|
+
return { bindings: scriptBlock.bindings, isScriptSetup: !!descriptor.scriptSetup };
|
|
5902
|
+
} catch {
|
|
5903
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
5904
|
+
}
|
|
5905
|
+
};
|
|
5906
|
+
const supplementHierarchyFromFilesystem = () => {
|
|
5907
|
+
const walkFilesRecursive = (rootDir) => {
|
|
5908
|
+
const out = [];
|
|
5909
|
+
const stack = [rootDir];
|
|
5910
|
+
while (stack.length) {
|
|
5911
|
+
const dir = stack.pop();
|
|
5912
|
+
if (!dir) continue;
|
|
5913
|
+
let entries = [];
|
|
5914
|
+
try {
|
|
5915
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
5916
|
+
} catch {
|
|
5917
|
+
continue;
|
|
5918
|
+
}
|
|
5919
|
+
for (const ent of entries) {
|
|
5920
|
+
if (ent.isDirectory()) {
|
|
5921
|
+
if (ent.name === "node_modules" || ent.name === ".git" || ent.name === "dist")
|
|
5922
|
+
continue;
|
|
5923
|
+
stack.push(path.join(dir, ent.name));
|
|
5924
|
+
continue;
|
|
5925
|
+
}
|
|
5926
|
+
if (ent.isFile() && ent.name.endsWith(".vue")) {
|
|
5927
|
+
out.push(path.join(dir, ent.name));
|
|
5928
|
+
}
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
return out;
|
|
5932
|
+
};
|
|
5933
|
+
let supplemented = 0;
|
|
5934
|
+
for (const dir of scanDirs) {
|
|
5935
|
+
const absDir = path.resolve(projectRootRef.current, dir);
|
|
5936
|
+
if (!fs.existsSync(absDir))
|
|
5937
|
+
continue;
|
|
5938
|
+
for (const filePath of walkFilesRecursive(absDir)) {
|
|
5939
|
+
const absolutePath = path.resolve(filePath);
|
|
5940
|
+
const componentName = resolveComponentNameFromPath({
|
|
5941
|
+
filename: absolutePath,
|
|
5942
|
+
projectRoot: projectRootRef.current,
|
|
5943
|
+
viewsDirAbs: getViewsDirAbs(),
|
|
5944
|
+
scanDirs,
|
|
5945
|
+
extraRoots: [process.cwd()]
|
|
5946
|
+
});
|
|
5947
|
+
if (componentHierarchyMap.has(componentName))
|
|
5948
|
+
continue;
|
|
5949
|
+
let sfc = "";
|
|
5950
|
+
try {
|
|
5951
|
+
sfc = fs.readFileSync(absolutePath, "utf8");
|
|
5952
|
+
} catch {
|
|
5953
|
+
continue;
|
|
5954
|
+
}
|
|
5955
|
+
const { descriptor } = parse$1(sfc, { filename: absolutePath });
|
|
5956
|
+
const template = descriptor.template?.content ?? "";
|
|
5957
|
+
if (!template.trim()) {
|
|
5958
|
+
vueFilesPathMap.set(componentName, absolutePath);
|
|
5959
|
+
componentHierarchyMap.set(componentName, {
|
|
5960
|
+
filePath: absolutePath,
|
|
5961
|
+
childrenComponentSet: /* @__PURE__ */ new Set(),
|
|
5962
|
+
usedComponentSet: /* @__PURE__ */ new Set(),
|
|
5963
|
+
dataTestIdSet: /* @__PURE__ */ new Set(),
|
|
5964
|
+
isView: false,
|
|
5965
|
+
methodsContent: ""
|
|
5966
|
+
});
|
|
5967
|
+
supplemented++;
|
|
5968
|
+
continue;
|
|
5969
|
+
}
|
|
5970
|
+
const { bindings: bindingMetadata, isScriptSetup } = getScriptInfo(sfc, absolutePath);
|
|
5971
|
+
vueFilesPathMap.set(componentName, absolutePath);
|
|
5972
|
+
try {
|
|
5973
|
+
compilerDom.compile(template, {
|
|
5974
|
+
filename: absolutePath,
|
|
5975
|
+
prefixIdentifiers: true,
|
|
5976
|
+
inline: isScriptSetup,
|
|
5977
|
+
bindingMetadata,
|
|
5978
|
+
nodeTransforms: [
|
|
5979
|
+
createTestIdTransform(
|
|
5980
|
+
componentName,
|
|
5981
|
+
componentHierarchyMap,
|
|
5982
|
+
nativeWrappers,
|
|
5983
|
+
excludedComponents,
|
|
5984
|
+
getViewsDirAbs(),
|
|
5985
|
+
{
|
|
5986
|
+
existingIdBehavior: existingIdBehavior ?? "preserve",
|
|
5987
|
+
testIdAttribute,
|
|
5988
|
+
nameCollisionBehavior,
|
|
5989
|
+
warn: (message) => loggerRef.current.warn(message),
|
|
5990
|
+
vueFilesPathMap,
|
|
5991
|
+
wrapperSearchRoots: getWrapperSearchRoots()
|
|
5992
|
+
}
|
|
5993
|
+
)
|
|
5994
|
+
]
|
|
5995
|
+
});
|
|
5996
|
+
} catch {
|
|
5997
|
+
}
|
|
5998
|
+
supplemented++;
|
|
5999
|
+
}
|
|
6000
|
+
}
|
|
6001
|
+
if (supplemented > 0) {
|
|
6002
|
+
loggerRef.current.info(`supplemented ${supplemented} components from filesystem walk (not in build graph)`);
|
|
6003
|
+
}
|
|
6004
|
+
};
|
|
6005
|
+
return {
|
|
6006
|
+
name: "vue-pom-generator-build",
|
|
6007
|
+
// This plugin exists to generate code on build output; it is not needed during dev-server HMR.
|
|
6008
|
+
apply: "build",
|
|
6009
|
+
enforce: "pre",
|
|
6010
|
+
async buildStart() {
|
|
6011
|
+
if (!routerAwarePoms) {
|
|
6012
|
+
setRouteNameToComponentNameMap(/* @__PURE__ */ new Map());
|
|
6013
|
+
setResolveToComponentNameFn(() => null);
|
|
6014
|
+
return;
|
|
6015
|
+
}
|
|
6016
|
+
let result;
|
|
6017
|
+
if (routerType === "nuxt") {
|
|
6018
|
+
result = await introspectNuxtPages(projectRootRef.current);
|
|
6019
|
+
} else {
|
|
6020
|
+
if (!resolvedRouterEntry)
|
|
6021
|
+
throw new Error("[vue-pom-generator] router.entry is required when router introspection is enabled.");
|
|
6022
|
+
result = await parseRouterFileFromCwd(resolvedRouterEntry, {
|
|
6023
|
+
moduleShims: routerModuleShims,
|
|
6024
|
+
componentNaming: {
|
|
6025
|
+
projectRoot: projectRootRef.current,
|
|
6026
|
+
viewsDirAbs: path.isAbsolute(viewsDir) ? viewsDir : path.resolve(projectRootRef.current, viewsDir),
|
|
6027
|
+
scanDirs
|
|
6028
|
+
}
|
|
6029
|
+
});
|
|
6030
|
+
}
|
|
6031
|
+
const { routeNameMap, routePathMap } = result;
|
|
6032
|
+
setRouteNameToComponentNameMap(routeNameMap);
|
|
6033
|
+
setResolveToComponentNameFn((to) => {
|
|
6034
|
+
if (typeof to === "string") {
|
|
6035
|
+
return routePathMap.get(to) ?? null;
|
|
6036
|
+
}
|
|
6037
|
+
const maybe = to;
|
|
6038
|
+
if (typeof maybe.name === "string" && maybe.name.length) {
|
|
6039
|
+
const key = toPascalCase(maybe.name);
|
|
6040
|
+
return routeNameMap.get(key) ?? null;
|
|
6041
|
+
}
|
|
6042
|
+
if (typeof maybe.path === "string" && maybe.path.length) {
|
|
6043
|
+
return routePathMap.get(maybe.path) ?? null;
|
|
6044
|
+
}
|
|
6045
|
+
return null;
|
|
6046
|
+
});
|
|
6047
|
+
if (!fs.existsSync(basePageClassPath)) {
|
|
6048
|
+
this.error(`BasePage.ts not found at ${basePageClassPath}. Ensure it is included in the build.`);
|
|
6049
|
+
}
|
|
6050
|
+
this.addWatchFile(basePageClassPath);
|
|
6051
|
+
const pointerPath = path.resolve(path.dirname(basePageClassPath), "Pointer.ts");
|
|
6052
|
+
if (!fs.existsSync(pointerPath)) {
|
|
6053
|
+
this.error(`Pointer.ts not found at ${pointerPath}. Ensure it is included in the build.`);
|
|
6054
|
+
}
|
|
6055
|
+
this.addWatchFile(pointerPath);
|
|
6056
|
+
},
|
|
6057
|
+
async buildEnd(error) {
|
|
6058
|
+
if (error) {
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
6061
|
+
supplementHierarchyFromFilesystem();
|
|
6062
|
+
const metrics = summarizeHierarchyMap(componentHierarchyMap);
|
|
6063
|
+
if (metrics.dataTestIdCount <= 0) {
|
|
6064
|
+
return;
|
|
6065
|
+
}
|
|
6066
|
+
if (isLessRich(metrics, lastGeneratedMetrics)) {
|
|
6067
|
+
return;
|
|
6068
|
+
}
|
|
6069
|
+
await generateFiles(componentHierarchyMap, vueFilesPathMap, normalizedBasePagePath, {
|
|
6070
|
+
outDir,
|
|
6071
|
+
emitLanguages,
|
|
6072
|
+
csharp,
|
|
6073
|
+
generateFixtures,
|
|
6074
|
+
customPomAttachments,
|
|
6075
|
+
projectRoot: projectRootRef.current,
|
|
6076
|
+
customPomDir,
|
|
6077
|
+
customPomImportAliases,
|
|
6078
|
+
customPomImportNameCollisionBehavior,
|
|
6079
|
+
testIdAttribute,
|
|
6080
|
+
vueRouterFluentChaining: routerAwarePoms,
|
|
6081
|
+
routerEntry: resolvedRouterEntry,
|
|
6082
|
+
routerType,
|
|
6083
|
+
viewsDir,
|
|
6084
|
+
scanDirs
|
|
6085
|
+
});
|
|
6086
|
+
lastGeneratedMetrics = metrics;
|
|
6087
|
+
loggerRef.current.info(`generated POMs (${metrics.entryCount} entries, ${metrics.interactiveComponentCount} interactive components, ${metrics.dataTestIdCount} selectors)`);
|
|
6088
|
+
},
|
|
6089
|
+
closeBundle() {
|
|
6090
|
+
loggerRef.current.info("build complete");
|
|
6091
|
+
}
|
|
6092
|
+
};
|
|
6093
|
+
}
|
|
5954
6094
|
function createDevProcessorPlugin(options) {
|
|
5955
6095
|
const {
|
|
5956
6096
|
nativeWrappers,
|
|
@@ -5970,6 +6110,7 @@ function createDevProcessorPlugin(options) {
|
|
|
5970
6110
|
customPomImportAliases,
|
|
5971
6111
|
customPomImportNameCollisionBehavior,
|
|
5972
6112
|
nameCollisionBehavior = "suffix",
|
|
6113
|
+
existingIdBehavior,
|
|
5973
6114
|
testIdAttribute,
|
|
5974
6115
|
routerAwarePoms,
|
|
5975
6116
|
resolvedRouterEntry,
|
|
@@ -6047,6 +6188,17 @@ function createDevProcessorPlugin(options) {
|
|
|
6047
6188
|
});
|
|
6048
6189
|
return descriptor.template?.content ?? "";
|
|
6049
6190
|
};
|
|
6191
|
+
const getScriptInfo = (source, filename) => {
|
|
6192
|
+
try {
|
|
6193
|
+
const { descriptor } = parse$1(source, { filename });
|
|
6194
|
+
if (!descriptor.script && !descriptor.scriptSetup)
|
|
6195
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
6196
|
+
const scriptBlock = compileScript(descriptor, { id: filename });
|
|
6197
|
+
return { bindings: scriptBlock.bindings, isScriptSetup: !!descriptor.scriptSetup };
|
|
6198
|
+
} catch {
|
|
6199
|
+
return { bindings: void 0, isScriptSetup: false };
|
|
6200
|
+
}
|
|
6201
|
+
};
|
|
6050
6202
|
const walkFilesRecursive = (rootDir) => {
|
|
6051
6203
|
const out = [];
|
|
6052
6204
|
const stack = [rootDir];
|
|
@@ -6106,9 +6258,12 @@ function createDevProcessorPlugin(options) {
|
|
|
6106
6258
|
const template = extractTemplateFromSfc(sfc, absolutePath);
|
|
6107
6259
|
if (!template.trim())
|
|
6108
6260
|
return { componentName, ms: performance.now() - started, compiled: true };
|
|
6261
|
+
const { bindings: bindingMetadata, isScriptSetup } = getScriptInfo(sfc, absolutePath);
|
|
6109
6262
|
compilerDom.compile(template, {
|
|
6110
6263
|
filename: absolutePath,
|
|
6111
6264
|
prefixIdentifiers: true,
|
|
6265
|
+
inline: isScriptSetup,
|
|
6266
|
+
bindingMetadata,
|
|
6112
6267
|
nodeTransforms: [
|
|
6113
6268
|
createTestIdTransform(
|
|
6114
6269
|
componentName,
|
|
@@ -6117,7 +6272,7 @@ function createDevProcessorPlugin(options) {
|
|
|
6117
6272
|
excludedComponents,
|
|
6118
6273
|
getViewsDirAbs(),
|
|
6119
6274
|
{
|
|
6120
|
-
existingIdBehavior: "preserve",
|
|
6275
|
+
existingIdBehavior: existingIdBehavior ?? "preserve",
|
|
6121
6276
|
nameCollisionBehavior,
|
|
6122
6277
|
testIdAttribute,
|
|
6123
6278
|
warn: (message) => loggerRef.current.warn(message),
|
|
@@ -6359,6 +6514,7 @@ function createSupportPlugins(options) {
|
|
|
6359
6514
|
scanDirs,
|
|
6360
6515
|
getWrapperSearchRoots,
|
|
6361
6516
|
nameCollisionBehavior = "suffix",
|
|
6517
|
+
existingIdBehavior,
|
|
6362
6518
|
outDir,
|
|
6363
6519
|
emitLanguages,
|
|
6364
6520
|
csharp,
|
|
@@ -6412,6 +6568,11 @@ function createSupportPlugins(options) {
|
|
|
6412
6568
|
customPomImportAliases,
|
|
6413
6569
|
customPomImportNameCollisionBehavior,
|
|
6414
6570
|
testIdAttribute,
|
|
6571
|
+
nameCollisionBehavior,
|
|
6572
|
+
existingIdBehavior,
|
|
6573
|
+
nativeWrappers,
|
|
6574
|
+
excludedComponents,
|
|
6575
|
+
getWrapperSearchRoots,
|
|
6415
6576
|
routerAwarePoms,
|
|
6416
6577
|
routerType,
|
|
6417
6578
|
resolvedRouterEntry,
|
|
@@ -6436,6 +6597,7 @@ function createSupportPlugins(options) {
|
|
|
6436
6597
|
customPomImportAliases,
|
|
6437
6598
|
customPomImportNameCollisionBehavior,
|
|
6438
6599
|
nameCollisionBehavior,
|
|
6600
|
+
existingIdBehavior,
|
|
6439
6601
|
testIdAttribute,
|
|
6440
6602
|
routerAwarePoms,
|
|
6441
6603
|
routerType,
|
|
@@ -7017,6 +7179,7 @@ function createVuePomGeneratorPlugins(options = {}) {
|
|
|
7017
7179
|
scanDirs,
|
|
7018
7180
|
getWrapperSearchRoots: getWrapperSearchRootsAbs,
|
|
7019
7181
|
nameCollisionBehavior,
|
|
7182
|
+
existingIdBehavior,
|
|
7020
7183
|
outDir,
|
|
7021
7184
|
emitLanguages,
|
|
7022
7185
|
csharp,
|