@immense/vue-pom-generator 1.0.37 → 1.0.38

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
@@ -45,6 +45,10 @@ If `generation.playwright.fixtures` is enabled, it also emits:
45
45
 
46
46
  - `tests/playwright/__generated__/fixtures.g.ts` (generated; do not edit)
47
47
 
48
+ Generated fixtures automatically prefer matching handwritten override classes from
49
+ `tests/playwright/pom/overrides/<ClassName>.ts` (or the sibling `overrides/` directory next to
50
+ your configured `generation.playwright.customPoms.dir`).
51
+
48
52
  ### Vite config example
49
53
 
50
54
  ```ts
@@ -202,6 +206,13 @@ Defaults:
202
206
 
203
207
  - when `true`: writes `fixtures.g.ts` alongside generated POMs (under `generation.outDir`)
204
208
 
209
+ Convention:
210
+
211
+ - if `tests/playwright/pom/overrides/<ClassName>.ts` exists, the generated fixture for that page/component
212
+ instantiates the override class instead of the raw generated `Pom.<ClassName>`
213
+ - the override directory is inferred as the sibling `overrides/` directory next to
214
+ `generation.playwright.customPoms.dir`
215
+
205
216
  ### Vite config example
206
217
 
207
218
  - `nativeWrappers` describes common wrapper components (e.g. design-system buttons/inputs)
package/RELEASE_NOTES.md CHANGED
@@ -1,44 +1,51 @@
1
- # Release Notes: v1.0.37
1
+ Now I have enough information to generate the release notes. The main feature is auto-wiring
2
+ fixture overrides in Playwright test fixtures.
3
+
4
+ ```markdown
5
+ # Release v1.0.38
2
6
 
3
7
  ## Highlights
4
8
 
5
- - Added support for external Vue plugin ownership, enabling better plugin architecture
6
- extensibility
7
- - Stabilized generator plugin refactor with improved plugin handling and configuration
8
- - Enhanced build plugin with expanded functionality (72+ lines added)
9
- - Refactored test suite with improved coverage and organization
10
- - Added automated PR release-notes preview comments to development workflow
9
+ - Playwright fixtures now automatically detect and use handwritten POM override classes
10
+ - Override classes in `overrides/<ClassName>.ts` are auto-wired when generating fixtures
11
+ - Enhanced test coverage for class generation and TypeScript compilation
12
+ - Updated documentation with fixture override conventions
11
13
 
12
14
  ## Changes
13
15
 
14
- ### Plugin System
15
- - Added external Vue plugin ownership support for more flexible plugin architecture
16
- - Refactored `create-vue-pom-generator-plugins.ts` with 134 lines of improvements
17
- - Enhanced `build-plugin.ts` with additional capabilities and refinements
18
- - Simplified `dev-plugin.ts` by removing ~34 lines of redundant code
19
- - Updated plugin types with new interfaces and type definitions
16
+ ### Playwright Fixture Generation
17
+
18
+ - Fixtures now automatically prefer matching handwritten override classes from the `overrides/`
19
+ directory
20
+ - Override directory location is inferred as sibling to `generation.playwright.customPoms.dir`
21
+ - Generated fixtures import and instantiate override classes when available (e.g.,
22
+ `tests/playwright/pom/overrides/<ClassName>.ts`)
23
+ - Added runtime detection of override files via filesystem checks during generation
20
24
 
21
25
  ### Documentation
22
- - Expanded README.md with 30+ lines of additional documentation
26
+
27
+ - Added fixture override convention documentation to README
28
+ - Updated plugin type definitions with fixture override behavior
29
+ - Documented override directory structure and lookup rules
23
30
 
24
31
  ### Testing
25
- - Restructured `options.test.ts` with 163 lines of changes for better test coverage and clarity
26
32
 
27
- ### Code Quality
28
- - Improved class generation logic
29
- - Refined Vue plugin integration points
33
+ - Expanded `tests/class-generation-coverage.test.ts` with fixture override scenarios
34
+ - Enhanced `tests/generated-tsc.test.ts` with 75+ additional lines of TypeScript compilation
35
+ tests
30
36
 
31
37
  ## Breaking Changes
32
38
 
33
- None identified.
39
+ None.
34
40
 
35
41
  ## Pull Requests Included
36
42
 
37
- - [#1](https://github.com/immense/vue-pom-generator/pull/1) Add PR release-notes preview
38
- comments (@dkattan)
43
+ - #1 Add PR release-notes preview comments https://github.com/immense/vue-pom-generator/pull/1
44
+ (by @dkattan)
39
45
 
40
46
  ## Testing
41
47
 
42
- Test suite refactored and expanded in `tests/options.test.ts` with improved organization and
43
- coverage.
48
+ Test coverage expanded significantly with new test cases for fixture override auto-wiring and
49
+ TypeScript compilation validation.
50
+ ```
44
51
 
@@ -321,6 +321,10 @@ export interface GenerateFilesOptions {
321
321
  * Default output (when `true`):
322
322
  * - `<projectRoot>/<outDir>/fixtures.g.ts`
323
323
  *
324
+ * Convention:
325
+ * - fixtures automatically prefer matching handwritten override classes from
326
+ * `<dirname(customPomDir)>/overrides/<ClassName>.ts` when present
327
+ *
324
328
  * Accepted values:
325
329
  * - `true`: enable with defaults
326
330
  * - `"path"`: enable and write the fixture file under this directory (resolved relative to projectRoot),
@@ -505,6 +509,7 @@ export async function generateFiles(
505
509
  generateFixtures,
506
510
  pomOutDir: outDir,
507
511
  projectRoot,
512
+ customPomDir,
508
513
  });
509
514
  if (fixtureRegistryFile) {
510
515
  writeGeneratedFile(fixtureRegistryFile);
@@ -1004,6 +1009,7 @@ function maybeGenerateFixtureRegistry(
1004
1009
  generateFixtures: GenerateFilesOptions["generateFixtures"];
1005
1010
  pomOutDir: string;
1006
1011
  projectRoot?: string;
1012
+ customPomDir?: string;
1007
1013
  },
1008
1014
  ): GeneratedFileOutput | null {
1009
1015
  const { generateFixtures, pomOutDir } = options;
@@ -1030,6 +1036,12 @@ function maybeGenerateFixtureRegistry(
1030
1036
  ? fixtureOutDirRel
1031
1037
  : path.resolve(root, fixtureOutDirRel);
1032
1038
 
1039
+ const customPomDirRel = options.customPomDir ?? "tests/playwright/pom/custom";
1040
+ const customPomDirAbs = path.isAbsolute(customPomDirRel)
1041
+ ? customPomDirRel
1042
+ : path.resolve(root, customPomDirRel);
1043
+ const overridePomDirAbs = path.resolve(path.dirname(customPomDirAbs), "overrides");
1044
+
1033
1045
  // Resolve the directory that contains the POM barrel export (e.g. <root>/pom).
1034
1046
  const pomDirAbs = path.isAbsolute(pomOutDir) ? pomOutDir : path.resolve(root, pomOutDir);
1035
1047
 
@@ -1066,6 +1078,29 @@ function maybeGenerateFixtureRegistry(
1066
1078
  })
1067
1079
  .sort((a, b) => a.localeCompare(b));
1068
1080
 
1081
+ const fixtureClassNames = [...viewClassNames, ...componentClassNames];
1082
+ const overrideCtorEntries = fixtureClassNames
1083
+ .map((name) => {
1084
+ const overrideFilePath = path.join(overridePomDirAbs, `${name}.ts`);
1085
+ if (!fs.existsSync(overrideFilePath))
1086
+ return null;
1087
+
1088
+ return {
1089
+ className: name,
1090
+ localIdentifier: `${name}Override`,
1091
+ importSpecifier: stripExtension(toPosixRelativePath(fixtureOutDirAbs, overrideFilePath)),
1092
+ };
1093
+ })
1094
+ .filter((entry): entry is { className: string; localIdentifier: string; importSpecifier: string } => !!entry);
1095
+ const overrideCtorByClassName = new Map(overrideCtorEntries.map(entry => [entry.className, entry.localIdentifier]));
1096
+ const overrideImports = overrideCtorEntries.length
1097
+ ? `${overrideCtorEntries
1098
+ .map(entry => `import { ${entry.className} as ${entry.localIdentifier} } from "${entry.importSpecifier}";`)
1099
+ .join("\n")}\n\n`
1100
+ : "";
1101
+
1102
+ const fixtureCtorExpression = (name: string) => overrideCtorByClassName.get(name) ?? `Pom.${name}`;
1103
+
1069
1104
  const header = `${eslintSuppressionHeader}/**\n`
1070
1105
  + ` * DO NOT MODIFY BY HAND\n`
1071
1106
  + ` *\n`
@@ -1079,11 +1114,11 @@ function maybeGenerateFixtureRegistry(
1079
1114
  // View POMs implement goTo() directly, so fixtures can be strongly typed without
1080
1115
  // casting/augmenting at runtime.
1081
1116
  const fixturesTypeEntries = viewClassNames
1082
- .map(name => ` ${lowerFirst(name)}: Pom.${name},`)
1117
+ .map(name => ` ${lowerFirst(name)}: ${fixtureCtorExpression(name)},`)
1083
1118
  .join("\n");
1084
1119
 
1085
1120
  const componentFixturesTypeEntries = componentClassNames
1086
- .map(name => ` ${lowerFirst(name)}: Pom.${name},`)
1121
+ .map(name => ` ${lowerFirst(name)}: ${fixtureCtorExpression(name)},`)
1087
1122
  .join("\n");
1088
1123
 
1089
1124
  const pomFactoryType = `export type PomConstructor<T> = new (page: PwPage) => T;\n\n`
@@ -1100,7 +1135,8 @@ function maybeGenerateFixtureRegistry(
1100
1135
  }/** Generated Playwright fixtures (typed page objects). */\n\n`
1101
1136
  + `import { expect, test as base } from "@playwright/test";\n`
1102
1137
  + `import type { Page as PwPage } from "@playwright/test";\n`
1103
- + `import * as Pom from "${pomImport}";\n\n`
1138
+ + `import * as Pom from "${pomImport}";\n`
1139
+ + `${overrideImports}`
1104
1140
  + `export interface PlaywrightOptions {\n`
1105
1141
  + ` animation: Pom.PlaywrightAnimationOptions;\n`
1106
1142
  + `}\n\n`
@@ -17,6 +17,10 @@ export interface GenerateFilesOptions {
17
17
  * Default output (when `true`):
18
18
  * - `<projectRoot>/<outDir>/fixtures.g.ts`
19
19
  *
20
+ * Convention:
21
+ * - fixtures automatically prefer matching handwritten override classes from
22
+ * `<dirname(customPomDir)>/overrides/<ClassName>.ts` when present
23
+ *
20
24
  * Accepted values:
21
25
  * - `true`: enable with defaults
22
26
  * - `"path"`: enable and write the fixture file under this directory (resolved relative to projectRoot),
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../class-generation/index.ts"],"names":[],"mappings":"AAIA,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;AAuPD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;OAWG;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,KAAK,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,wBAAwB,EAAE,MAAM,EAAE,CAAC;QAEnC;;;WAGG;QACH,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;KAC5C,CAAC,CAAC;IAEH,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;AAwCD,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,iBAkFnC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../class-generation/index.ts"],"names":[],"mappings":"AAIA,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;AAuPD,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,KAAK,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,wBAAwB,EAAE,MAAM,EAAE,CAAC;QAEnC;;;WAGG;QACH,QAAQ,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;KAC5C,CAAC,CAAC;IAEH,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;AAwCD,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
@@ -3519,7 +3519,8 @@ async function generateFiles(componentHierarchyMap, vueFilesPathMap, basePageCla
3519
3519
  const fixtureRegistryFile = maybeGenerateFixtureRegistry(componentHierarchyMap, {
3520
3520
  generateFixtures,
3521
3521
  pomOutDir: outDir,
3522
- projectRoot
3522
+ projectRoot,
3523
+ customPomDir
3523
3524
  });
3524
3525
  if (fixtureRegistryFile) {
3525
3526
  writeGeneratedFile(fixtureRegistryFile);
@@ -3918,6 +3919,9 @@ function maybeGenerateFixtureRegistry(componentHierarchyMap, options) {
3918
3919
  const fixtureFileName = looksLikeFilePath ? path.basename(fixtureOutRel) : "fixtures.g.ts";
3919
3920
  const root = options.projectRoot ?? process.cwd();
3920
3921
  const fixtureOutDirAbs = path.isAbsolute(fixtureOutDirRel) ? fixtureOutDirRel : path.resolve(root, fixtureOutDirRel);
3922
+ const customPomDirRel = options.customPomDir ?? "tests/playwright/pom/custom";
3923
+ const customPomDirAbs = path.isAbsolute(customPomDirRel) ? customPomDirRel : path.resolve(root, customPomDirRel);
3924
+ const overridePomDirAbs = path.resolve(path.dirname(customPomDirAbs), "overrides");
3921
3925
  const pomDirAbs = path.isAbsolute(pomOutDir) ? pomOutDir : path.resolve(root, pomOutDir);
3922
3926
  const pomImport = toPosixRelativePath(fixtureOutDirAbs, pomDirAbs);
3923
3927
  const viewClassNames = Array.from(componentHierarchyMap.entries()).filter(([, deps]) => !!deps.isView).map(([name]) => name).sort((a, b) => a.localeCompare(b));
@@ -3940,6 +3944,22 @@ function maybeGenerateFixtureRegistry(componentHierarchyMap, options) {
3940
3944
  return false;
3941
3945
  return true;
3942
3946
  }).sort((a, b) => a.localeCompare(b));
3947
+ const fixtureClassNames = [...viewClassNames, ...componentClassNames];
3948
+ const overrideCtorEntries = fixtureClassNames.map((name) => {
3949
+ const overrideFilePath = path.join(overridePomDirAbs, `${name}.ts`);
3950
+ if (!fs.existsSync(overrideFilePath))
3951
+ return null;
3952
+ return {
3953
+ className: name,
3954
+ localIdentifier: `${name}Override`,
3955
+ importSpecifier: stripExtension(toPosixRelativePath(fixtureOutDirAbs, overrideFilePath))
3956
+ };
3957
+ }).filter((entry) => !!entry);
3958
+ const overrideCtorByClassName = new Map(overrideCtorEntries.map((entry) => [entry.className, entry.localIdentifier]));
3959
+ const overrideImports = overrideCtorEntries.length ? `${overrideCtorEntries.map((entry) => `import { ${entry.className} as ${entry.localIdentifier} } from "${entry.importSpecifier}";`).join("\n")}
3960
+
3961
+ ` : "";
3962
+ const fixtureCtorExpression = (name) => overrideCtorByClassName.get(name) ?? `Pom.${name}`;
3943
3963
  const header = `${eslintSuppressionHeader}/**
3944
3964
  * DO NOT MODIFY BY HAND
3945
3965
  *
@@ -3948,8 +3968,8 @@ function maybeGenerateFixtureRegistry(componentHierarchyMap, options) {
3948
3968
  */
3949
3969
 
3950
3970
  `;
3951
- const fixturesTypeEntries = viewClassNames.map((name) => ` ${lowerFirst(name)}: Pom.${name},`).join("\n");
3952
- const componentFixturesTypeEntries = componentClassNames.map((name) => ` ${lowerFirst(name)}: Pom.${name},`).join("\n");
3971
+ const fixturesTypeEntries = viewClassNames.map((name) => ` ${lowerFirst(name)}: ${fixtureCtorExpression(name)},`).join("\n");
3972
+ const componentFixturesTypeEntries = componentClassNames.map((name) => ` ${lowerFirst(name)}: ${fixtureCtorExpression(name)},`).join("\n");
3953
3973
  const pomFactoryType = `export type PomConstructor<T> = new (page: PwPage) => T;
3954
3974
 
3955
3975
  export interface PomFactory {
@@ -3962,8 +3982,7 @@ export interface PomFactory {
3962
3982
  import { expect, test as base } from "@playwright/test";
3963
3983
  import type { Page as PwPage } from "@playwright/test";
3964
3984
  import * as Pom from "${pomImport}";
3965
-
3966
- export interface PlaywrightOptions {
3985
+ ${overrideImports}export interface PlaywrightOptions {
3967
3986
  animation: Pom.PlaywrightAnimationOptions;
3968
3987
  }
3969
3988