@immense/vue-pom-generator 1.0.52 → 1.0.54
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 +71 -27
- package/RELEASE_NOTES.md +38 -27
- package/class-generation/base-page.ts +18 -6
- package/class-generation/callout.ts +229 -679
- package/class-generation/floating-ui-callout.ts +857 -0
- package/class-generation/index.ts +24 -15
- package/class-generation/pointer.ts +152 -109
- package/dist/class-generation/base-page.d.ts +11 -5
- package/dist/class-generation/base-page.d.ts.map +1 -1
- package/dist/class-generation/callout.d.ts +44 -1
- package/dist/class-generation/callout.d.ts.map +1 -1
- package/dist/class-generation/floating-ui-callout.d.ts +4 -0
- package/dist/class-generation/floating-ui-callout.d.ts.map +1 -0
- package/dist/class-generation/index.d.ts +3 -2
- package/dist/class-generation/index.d.ts.map +1 -1
- package/dist/class-generation/pointer.d.ts +24 -5
- package/dist/class-generation/pointer.d.ts.map +1 -1
- package/dist/index.cjs +783 -231
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +783 -231
- package/dist/index.mjs.map +1 -1
- package/dist/plugin/create-vue-pom-generator-plugins.d.ts +2 -2
- package/dist/plugin/create-vue-pom-generator-plugins.d.ts.map +1 -1
- package/dist/plugin/nuxt-discovery.d.ts +47 -0
- package/dist/plugin/nuxt-discovery.d.ts.map +1 -0
- package/dist/plugin/path-utils.d.ts +4 -5
- package/dist/plugin/path-utils.d.ts.map +1 -1
- package/dist/plugin/support/build-plugin.d.ts +6 -3
- package/dist/plugin/support/build-plugin.d.ts.map +1 -1
- package/dist/plugin/support/dev-plugin.d.ts +6 -3
- package/dist/plugin/support/dev-plugin.d.ts.map +1 -1
- package/dist/plugin/support/virtual-modules.d.ts +2 -2
- package/dist/plugin/support/virtual-modules.d.ts.map +1 -1
- package/dist/plugin/support-plugins.d.ts +5 -2
- package/dist/plugin/support-plugins.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +35 -19
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/vue-plugin.d.ts +1 -1
- package/dist/plugin/vue-plugin.d.ts.map +1 -1
- package/dist/router-introspection.d.ts +4 -2
- package/dist/router-introspection.d.ts.map +1 -1
- package/dist/tests/nuxt-discovery.test.d.ts +2 -0
- package/dist/tests/nuxt-discovery.test.d.ts.map +1 -0
- package/dist/vite.config.d.ts.map +1 -1
- package/package.json +9 -13
- package/dist/plugin/support/generation-metrics.d.ts +0 -10
- package/dist/plugin/support/generation-metrics.d.ts.map +0 -1
- package/dist/tests/generation-metrics.test.d.ts +0 -2
- package/dist/tests/generation-metrics.test.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ The generator does not use one naming trick. It layers several signals.
|
|
|
74
74
|
- **Router links / `:to` bindings** can contribute route-based naming and typed navigation return types when the target can be resolved.
|
|
75
75
|
- **Wrapper components** can be explicit (`nativeWrappers`) or inferred from simple local SFC templates.
|
|
76
76
|
- **Fallback naming exists, but it is intentionally conservative.** That is why `generation.nameCollisionBehavior` exists.
|
|
77
|
-
- **
|
|
77
|
+
- **Wrapper-action generation fails fast by default.** The generator blocks button-like wrapper `:handler` expressions that it cannot turn into a semantic action name; set `errorBehavior: "ignore"` if you explicitly want the old permissive fallback.
|
|
78
78
|
|
|
79
79
|
Important limit: wrapper inference is helpful, not magical. The current implementation recursively inspects simple local SFC templates for the first inferable primitive (`input`, `textarea`, `select`, `button`, `vselect`, radio/checkbox inputs). It also recognizes some naming patterns like `*Button`. For anything more complex, configure `nativeWrappers` explicitly.
|
|
80
80
|
|
|
@@ -191,9 +191,10 @@ Exports:
|
|
|
191
191
|
- `createVuePomGeneratorPlugins()`
|
|
192
192
|
- `vuePomGenerator()` (alias)
|
|
193
193
|
- `defineVuePomGeneratorConfig()`
|
|
194
|
+
- `defineNuxtPomGeneratorConfig()`
|
|
194
195
|
- `@immense/vue-pom-generator/eslint`
|
|
195
196
|
|
|
196
|
-
## Basic Vite setup
|
|
197
|
+
## Basic Vue/Vite setup
|
|
197
198
|
|
|
198
199
|
```ts
|
|
199
200
|
import { defineConfig } from "vite";
|
|
@@ -208,7 +209,8 @@ const pomConfig = defineVuePomGeneratorConfig({
|
|
|
208
209
|
injection: {
|
|
209
210
|
attribute: "data-testid",
|
|
210
211
|
viewsDir: "src/views",
|
|
211
|
-
|
|
212
|
+
componentDirs: ["src/components"],
|
|
213
|
+
layoutDirs: ["src/layouts"],
|
|
212
214
|
wrapperSearchRoots: ["../shared-ui/src/components"],
|
|
213
215
|
nativeWrappers: {
|
|
214
216
|
AppButton: { role: "button" },
|
|
@@ -261,6 +263,29 @@ export default defineConfig({
|
|
|
261
263
|
});
|
|
262
264
|
```
|
|
263
265
|
|
|
266
|
+
## Basic Nuxt setup
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
import { defineNuxtConfig } from "nuxt/config";
|
|
270
|
+
import { defineNuxtPomGeneratorConfig, vuePomGenerator } from "@immense/vue-pom-generator";
|
|
271
|
+
|
|
272
|
+
const pomConfig = defineNuxtPomGeneratorConfig({
|
|
273
|
+
generation: {
|
|
274
|
+
outDir: "tests/playwright/__generated__",
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
export default defineNuxtConfig({
|
|
279
|
+
vite: {
|
|
280
|
+
plugins: [
|
|
281
|
+
...vuePomGenerator(pomConfig),
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Nuxt projects are auto-detected from standard project artifacts, and their pages/layouts/components are resolved from Nuxt's own config. That means custom page directories such as `dir.pages = "views"` come from `nuxt.config`, while component directories are picked up automatically from Nuxt conventions/config. `defineNuxtPomGeneratorConfig(...)` is optional, but it keeps the config surface Nuxt-specific at type-check time.
|
|
288
|
+
|
|
264
289
|
### Important Vite ownership rule
|
|
265
290
|
|
|
266
291
|
By default, this package creates and returns its own `@vitejs/plugin-vue` instance.
|
|
@@ -289,7 +314,7 @@ export default defineConfig({
|
|
|
289
314
|
});
|
|
290
315
|
```
|
|
291
316
|
|
|
292
|
-
Nuxt-style routing also uses the resolved app-owned Vue plugin. In practice,
|
|
317
|
+
Nuxt-style routing also uses the resolved app-owned Vue plugin. In practice, Nuxt projects are auto-detected and use external Vue plugin ownership automatically.
|
|
293
318
|
|
|
294
319
|
## What gets generated
|
|
295
320
|
|
|
@@ -320,7 +345,7 @@ If you emit outside a `__generated__` path, the generator also manages `.gitattr
|
|
|
320
345
|
|
|
321
346
|
This is important if you are deciding whether the tool will fit into a real codebase.
|
|
322
347
|
|
|
323
|
-
- **Dev server:** on startup, it scans the configured
|
|
348
|
+
- **Dev server:** on startup, it scans the configured Vue page/component/layout directories (or the directories resolved from Nuxt config in Nuxt mode), compiles each `.vue` file into a snapshot, writes the configured TypeScript outputs once, then batches add/change/delete events and regenerates incrementally.
|
|
324
349
|
- **Build:** it generates from the richest build pass it sees, which matters because Vite can run multiple passes (for example SSR plus client). The generator avoids letting a thinner pass clobber a richer one.
|
|
325
350
|
- **Always-on virtual module:** `virtual:testids` is registered whether generation is enabled or disabled.
|
|
326
351
|
- **Generation can be disabled:** `generation: false` still keeps compile-time test-id injection and the virtual module, but skips emitted POM files.
|
|
@@ -592,6 +617,7 @@ What it gives you:
|
|
|
592
617
|
- lower-camel-case fixtures for component classes too
|
|
593
618
|
- `pomFactory.create(Ctor)` for ad-hoc page-object construction inside tests
|
|
594
619
|
- an `animation` option that wires the generated runtime's pointer settings
|
|
620
|
+
- per-page `renderers` overrides so you can keep the simple default callout or swap in a custom pointer / callout overlay implementation such as the bundled `floating-ui-callout.ts` renderer
|
|
595
621
|
|
|
596
622
|
Current caveats:
|
|
597
623
|
|
|
@@ -600,6 +626,12 @@ Current caveats:
|
|
|
600
626
|
- component fixtures are skipped when their lower-camel-case name would collide with reserved Playwright fixture names such as `page`, `context`, `browser`, or `request`
|
|
601
627
|
- an override class still needs a `new (page)`-compatible constructor because that is what fixtures call
|
|
602
628
|
|
|
629
|
+
By default the runtime uses a simple red fallback bubble. The example below uses the optional floating-ui renderer so the callout can auto-place around nearby UI and point back to the target with an arrow.
|
|
630
|
+
|
|
631
|
+
Example floating-ui callout sequence captured from the Playwright fixture coverage:
|
|
632
|
+
|
|
633
|
+

|
|
634
|
+
|
|
603
635
|
## TypeScript vs C# output
|
|
604
636
|
|
|
605
637
|
### TypeScript output
|
|
@@ -821,12 +853,12 @@ The sections below follow the actual `VuePomGeneratorPluginOptions` shape from `
|
|
|
821
853
|
|
|
822
854
|
- **What it does:** Controls strict/error behavior for generator checks.
|
|
823
855
|
- **Why it exists:** complex inline handlers can otherwise fall through to generic naming, which makes generated APIs harder to discover and review.
|
|
824
|
-
- **Benefit:**
|
|
825
|
-
- **Without it:** the default is `"
|
|
856
|
+
- **Benefit:** fail-fast behavior is the default, while `"ignore"` or the object form let you opt back into only the permissive checks you want.
|
|
857
|
+
- **Without it:** the default is `"error"`, so unsupported button-wrapper handlers stop generation instead of silently falling back.
|
|
826
858
|
- **Accepted values:**
|
|
827
859
|
- `"ignore"` — keep permissive defaults for all supported checks
|
|
828
|
-
- `"error"` — enable error-on-failure behavior for all supported checks
|
|
829
|
-
- `{ missingSemanticNameBehavior: "
|
|
860
|
+
- `"error"` — enable error-on-failure behavior for all supported checks (default)
|
|
861
|
+
- `{ missingSemanticNameBehavior: "ignore" }` — opt out only of the button-wrapper semantic-name check
|
|
830
862
|
- **Current scope:** this first pass is intentionally narrow. The object form currently supports `missingSemanticNameBehavior`, which targets button-like wrappers with `:handler`; value/model-driven wrappers still use their existing naming flow.
|
|
831
863
|
|
|
832
864
|
### `injection`
|
|
@@ -857,6 +889,30 @@ The sections below follow the actual `VuePomGeneratorPluginOptions` shape from `
|
|
|
857
889
|
injection: { viewsDir: "app/pages" }
|
|
858
890
|
```
|
|
859
891
|
|
|
892
|
+
#### `injection.componentDirs`
|
|
893
|
+
|
|
894
|
+
- **What it does:** Lists the directories that should be treated as reusable component roots.
|
|
895
|
+
- **Why it exists:** Vue apps often keep components outside a single catch-all tree, and the generator needs explicit component roots now that generic scan lists are gone.
|
|
896
|
+
- **Benefit:** component naming and filesystem supplementation stay aligned with the directories you actually consider components.
|
|
897
|
+
- **Without it:** the generator uses `["src/components"]`.
|
|
898
|
+
- **Example:**
|
|
899
|
+
|
|
900
|
+
```ts
|
|
901
|
+
injection: { componentDirs: ["src/components", "../shared-ui/src/components"] }
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
#### `injection.layoutDirs`
|
|
905
|
+
|
|
906
|
+
- **What it does:** Lists layout-style Vue directories that should be included in generation and naming.
|
|
907
|
+
- **Why it exists:** some Vue apps keep shell components outside `views` and `components`, but still want them in the generated POM graph.
|
|
908
|
+
- **Benefit:** layouts participate explicitly without falling back to a generic scan of unrelated folders.
|
|
909
|
+
- **Without it:** the generator uses `["src/layouts"]`.
|
|
910
|
+
- **Example:**
|
|
911
|
+
|
|
912
|
+
```ts
|
|
913
|
+
injection: { layoutDirs: ["src/layouts"] }
|
|
914
|
+
```
|
|
915
|
+
|
|
860
916
|
#### `injection.nativeWrappers`
|
|
861
917
|
|
|
862
918
|
- **What it does:** Describes wrapper components so the generator can treat them like native controls.
|
|
@@ -910,24 +966,12 @@ The sections below follow the actual `VuePomGeneratorPluginOptions` shape from `
|
|
|
910
966
|
injection: { excludeComponents: ["LegacyWidget"] }
|
|
911
967
|
```
|
|
912
968
|
|
|
913
|
-
#### `injection.scanDirs`
|
|
914
|
-
|
|
915
|
-
- **What it does:** Sets which directories are scanned for `.vue` files when building the POM graph.
|
|
916
|
-
- **Why it exists:** real projects rarely keep all SFCs under one folder, especially in Nuxt or monorepos.
|
|
917
|
-
- **Benefit:** generation sees the same files your app actually uses.
|
|
918
|
-
- **Without it:** the generator scans `src`.
|
|
919
|
-
- **Example:**
|
|
920
|
-
|
|
921
|
-
```ts
|
|
922
|
-
injection: { scanDirs: ["src", "components", "layouts"] }
|
|
923
|
-
```
|
|
924
|
-
|
|
925
969
|
#### `injection.wrapperSearchRoots`
|
|
926
970
|
|
|
927
|
-
- **What it does:** Adds extra roots for wrapper inference outside
|
|
971
|
+
- **What it does:** Adds extra roots for wrapper inference outside the configured page/component/layout directories.
|
|
928
972
|
- **Why it exists:** wrapper components often live in sibling packages or shared UI workspaces.
|
|
929
973
|
- **Benefit:** local wrapper inference can still work across package boundaries.
|
|
930
|
-
- **Without it:** no extra wrapper lookup is done outside the
|
|
974
|
+
- **Without it:** no extra wrapper lookup is done outside the configured app directories.
|
|
931
975
|
- **Example:**
|
|
932
976
|
|
|
933
977
|
```ts
|
|
@@ -1013,13 +1057,13 @@ If omitted, router introspection is off.
|
|
|
1013
1057
|
|
|
1014
1058
|
#### `generation.router.type`
|
|
1015
1059
|
|
|
1016
|
-
- **What it does:** Chooses the router discovery strategy.
|
|
1017
|
-
- **Why it exists:**
|
|
1018
|
-
- **Benefit:**
|
|
1060
|
+
- **What it does:** Chooses the Vue-router discovery strategy for standard Vue apps.
|
|
1061
|
+
- **Why it exists:** some Vue apps want router introspection without any Nuxt integration.
|
|
1062
|
+
- **Benefit:** keeps Vue-router discovery explicit.
|
|
1019
1063
|
- **Without it:** defaults to `"vue-router"`.
|
|
1064
|
+
- **Nuxt note:** Nuxt projects are auto-detected. Do not set `generation.router.type: "nuxt"`.
|
|
1020
1065
|
- **Current options:**
|
|
1021
1066
|
- `"vue-router"`
|
|
1022
|
-
- `"nuxt"`
|
|
1023
1067
|
|
|
1024
1068
|
#### `generation.router.moduleShims`
|
|
1025
1069
|
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,43 +1,54 @@
|
|
|
1
|
-
●
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
1
|
+
● ## Highlights
|
|
2
|
+
|
|
3
|
+
- **Zero runtime dependencies**: Eliminated all runtime dependencies for smaller bundle size and
|
|
4
|
+
reduced version conflicts
|
|
5
|
+
- **Pluggable callout renderer architecture**: Extracted floating-ui implementation into
|
|
6
|
+
swappable renderer system
|
|
7
|
+
- **Stricter semantic naming**: Unnameable wrapper handlers now fail fast by default instead of
|
|
8
|
+
silently succeeding
|
|
9
|
+
- **Streamlined callout placement pipeline**: Refactored pointer callout rendering for improved
|
|
10
|
+
maintainability
|
|
11
|
+
- **Removed peer dependencies**: No longer requires `vue`, `vitest`, or `@vue/shared` as peer
|
|
12
|
+
dependencies
|
|
9
13
|
|
|
10
14
|
## Changes
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
-
|
|
16
|
+
### Dependencies
|
|
17
|
+
- Eliminated all runtime dependencies
|
|
18
|
+
([#9](https://github.com/immense/vue-pom-generator/pull/9))
|
|
19
|
+
- Removed `vue`, `vitest`, and `@vue/shared` peer dependencies
|
|
20
|
+
- Updated package structure for zero external runtime requirements
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
22
|
+
### Callout Rendering
|
|
23
|
+
- Extracted floating-ui callout renderer into separate module (`floating-ui-callout.ts`)
|
|
24
|
+
- Introduced pluggable pointer callout renderer system
|
|
25
|
+
- Streamlined callout placement pipeline for better performance
|
|
26
|
+
- Refactored pointer rendering logic for extensibility
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- Improved runtime generation to meet updated lint expectations
|
|
28
|
+
### Error Handling
|
|
29
|
+
- Semantic-name validation failures now default to throwing errors instead of warnings
|
|
30
|
+
- Improved fail-fast behavior for unnameable wrapper handlers
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- Enhanced
|
|
32
|
+
### Testing
|
|
33
|
+
- Aligned dev plugin options across test suite
|
|
34
|
+
- Added pointer callout sequence documentation (GIF)
|
|
35
|
+
- Enhanced test coverage for pointer rendering
|
|
30
36
|
|
|
31
37
|
## Breaking Changes
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
- **Peer dependencies removed**: `vue`, `vitest`, and `@vue/shared` are no longer peer
|
|
40
|
+
dependencies. Ensure your build still works if you relied on these being present.
|
|
41
|
+
- **Semantic naming errors**: Invalid semantic names now throw by default instead of warning.
|
|
42
|
+
Handlers that cannot be named semantically will cause build failures unless explicitly
|
|
43
|
+
configured otherwise.
|
|
34
44
|
|
|
35
45
|
## Pull Requests Included
|
|
36
46
|
|
|
37
|
-
- #
|
|
47
|
+
- [#9](https://github.com/immense/vue-pom-generator/pull/9) - refactor(deps): eliminate all
|
|
48
|
+
runtime dependencies
|
|
38
49
|
|
|
39
50
|
## Testing
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
Comprehensive test updates included to validate dependency removal, plugin option alignment, and
|
|
53
|
+
pointer callout rendering behavior.
|
|
43
54
|
|
|
@@ -2,8 +2,8 @@ import type { PwLocator, PwPage } from "./playwright-types";
|
|
|
2
2
|
import { TESTID_CLICK_EVENT_NAME, TESTID_CLICK_EVENT_STRICT_FLAG } from "../click-instrumentation";
|
|
3
3
|
import type { TestIdClickEventDetail } from "../click-instrumentation";
|
|
4
4
|
import { Callout } from "./callout";
|
|
5
|
-
import {
|
|
6
|
-
import type
|
|
5
|
+
import type { CalloutRenderer } from "./callout";
|
|
6
|
+
import { Pointer, type AfterPointerClick, type AfterPointerClickInfo, type PointerRenderer } from "./pointer";
|
|
7
7
|
|
|
8
8
|
// Click instrumentation is optional for generated POMs.
|
|
9
9
|
//
|
|
@@ -55,6 +55,14 @@ export type Fluent<T extends object> = DeepFluent<T, T> & PromiseLike<T>;
|
|
|
55
55
|
|
|
56
56
|
export type ValueFluent<T> = DeepValueFluent<T> & PromiseLike<T>;
|
|
57
57
|
|
|
58
|
+
export interface BasePageOptions {
|
|
59
|
+
renderers?: {
|
|
60
|
+
callout?: CalloutRenderer;
|
|
61
|
+
pointer?: PointerRenderer;
|
|
62
|
+
};
|
|
63
|
+
testIdAttribute?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
export class ObjectId {
|
|
59
67
|
private readonly raw: string;
|
|
60
68
|
|
|
@@ -99,11 +107,15 @@ export class BasePage {
|
|
|
99
107
|
/**
|
|
100
108
|
* @param {Page} page - Playwright page object
|
|
101
109
|
*/
|
|
102
|
-
constructor(protected page: PwPage, options?:
|
|
110
|
+
public constructor(protected page: PwPage, options?: BasePageOptions) {
|
|
103
111
|
this.testIdAttribute = (options?.testIdAttribute || "data-testid").trim() || "data-testid";
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
this.
|
|
113
|
+
const pointerRenderer = options?.renderers?.pointer;
|
|
114
|
+
this.callout = new Callout(this.page, {
|
|
115
|
+
extraOverlayIds: pointerRenderer?.overlayIds,
|
|
116
|
+
renderer: options?.renderers?.callout,
|
|
117
|
+
});
|
|
118
|
+
this.pointer = new Pointer(this.page, this.testIdAttribute, this.callout, pointerRenderer);
|
|
107
119
|
}
|
|
108
120
|
|
|
109
121
|
private async waitForTestIdClickEventAfter(testId: string, options?: { timeoutMs?: number }): Promise<void> {
|
|
@@ -237,7 +249,7 @@ export class BasePage {
|
|
|
237
249
|
}
|
|
238
250
|
|
|
239
251
|
/**
|
|
240
|
-
* Animates the
|
|
252
|
+
* Animates the pointer to an element.
|
|
241
253
|
*/
|
|
242
254
|
protected async animateCursorToElement(
|
|
243
255
|
target: string | PwLocator,
|