@qawolf/pom 0.0.1

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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/basePageObject.d.ts +50 -0
  4. package/dist/basePageObject.d.ts.map +1 -0
  5. package/dist/basePageObject.js +41 -0
  6. package/dist/basePageObject.js.map +1 -0
  7. package/dist/cleanupUtils.d.ts +29 -0
  8. package/dist/cleanupUtils.d.ts.map +1 -0
  9. package/dist/cleanupUtils.js +62 -0
  10. package/dist/cleanupUtils.js.map +1 -0
  11. package/dist/entryPointPageObject.d.ts +44 -0
  12. package/dist/entryPointPageObject.d.ts.map +1 -0
  13. package/dist/entryPointPageObject.js +116 -0
  14. package/dist/entryPointPageObject.js.map +1 -0
  15. package/dist/index.d.ts +35 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +10 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/networkMonitor.d.ts +35 -0
  20. package/dist/networkMonitor.d.ts.map +1 -0
  21. package/dist/networkMonitor.js +70 -0
  22. package/dist/networkMonitor.js.map +1 -0
  23. package/dist/pageHookCollection.d.ts +20 -0
  24. package/dist/pageHookCollection.d.ts.map +1 -0
  25. package/dist/pageHookCollection.js +29 -0
  26. package/dist/pageHookCollection.js.map +1 -0
  27. package/dist/pageHooks.d.ts +43 -0
  28. package/dist/pageHooks.d.ts.map +1 -0
  29. package/dist/pageHooks.js +2 -0
  30. package/dist/pageHooks.js.map +1 -0
  31. package/dist/pageRegistry.d.ts +58 -0
  32. package/dist/pageRegistry.d.ts.map +1 -0
  33. package/dist/pageRegistry.js +79 -0
  34. package/dist/pageRegistry.js.map +1 -0
  35. package/dist/platformClient.d.ts +11 -0
  36. package/dist/platformClient.d.ts.map +1 -0
  37. package/dist/platformClient.js +27 -0
  38. package/dist/platformClient.js.map +1 -0
  39. package/dist/popupHandler.d.ts +18 -0
  40. package/dist/popupHandler.d.ts.map +1 -0
  41. package/dist/popupHandler.js +46 -0
  42. package/dist/popupHandler.js.map +1 -0
  43. package/dist/popupShieldInitScript.d.ts +11 -0
  44. package/dist/popupShieldInitScript.d.ts.map +1 -0
  45. package/dist/popupShieldInitScript.js +45 -0
  46. package/dist/popupShieldInitScript.js.map +1 -0
  47. package/dist/sequence.d.ts +2 -0
  48. package/dist/sequence.d.ts.map +1 -0
  49. package/dist/sequence.js +2 -0
  50. package/dist/sequence.js.map +1 -0
  51. package/dist/subPageObject.d.ts +9 -0
  52. package/dist/subPageObject.d.ts.map +1 -0
  53. package/dist/subPageObject.js +9 -0
  54. package/dist/subPageObject.js.map +1 -0
  55. package/dist/testDataUtilities.d.ts +7 -0
  56. package/dist/testDataUtilities.d.ts.map +1 -0
  57. package/dist/testDataUtilities.js +21 -0
  58. package/dist/testDataUtilities.js.map +1 -0
  59. package/package.json +57 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageHookCollection.d.ts","sourceRoot":"","sources":["../src/pageHookCollection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAuB3E,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,GACT,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,EAAE,CAAA;CAAE,EAAE,CAAC,CAQ3D;AAED,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,IAAI,GACT,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,mBAAmB,EAAE,CAAA;CAAE,EAAE,CAAC,CAQ/D"}
@@ -0,0 +1,29 @@
1
+ import { classDeclaresPageHooks, entries, loadPageClass, } from "./pageRegistry.js";
2
+ async function resolveHookBearingClasses() {
3
+ const resolved = await Promise.all(Object.entries(entries).map(async ([name, entry]) => {
4
+ if (entry.kind === "lazy" && entry.providesPageHooks === false)
5
+ return undefined;
6
+ const cls = entry.kind === "eager" ? entry.cls : await loadPageClass(name, entry);
7
+ return classDeclaresPageHooks(cls) ? { cls, name } : undefined;
8
+ }));
9
+ return resolved.filter((entry) => entry !== undefined);
10
+ }
11
+ export async function getRegisteredPopupHandlers(page) {
12
+ const hookBearing = await resolveHookBearingClasses();
13
+ return hookBearing
14
+ .filter(({ cls }) => Object.hasOwn(cls.prototype, "popupHandlers"))
15
+ .map(({ cls, name }) => ({
16
+ className: name,
17
+ defs: cls.createFromPage(page).popupHandlers(),
18
+ }));
19
+ }
20
+ export async function getRegisteredRouteInterceptors(page) {
21
+ const hookBearing = await resolveHookBearingClasses();
22
+ return hookBearing
23
+ .filter(({ cls }) => Object.hasOwn(cls.prototype, "routeInterceptors"))
24
+ .map(({ cls, name }) => ({
25
+ className: name,
26
+ defs: cls.createFromPage(page).routeInterceptors(),
27
+ }));
28
+ }
29
+ //# sourceMappingURL=pageHookCollection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageHookCollection.js","sourceRoot":"","sources":["../src/pageHookCollection.ts"],"names":[],"mappings":"AAYA,OAAO,EAEL,sBAAsB,EACtB,OAAO,EACP,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,KAAK,UAAU,yBAAyB;IAGtC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QAClD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,KAAK;YAC5D,OAAO,SAAS,CAAC;QACnB,MAAM,GAAG,GACP,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxE,OAAO,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,CAAC,CAAC,CACH,CAAC;IACF,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,IAAU;IAEV,MAAM,WAAW,GAAG,MAAM,yBAAyB,EAAE,CAAC;IACtD,OAAO,WAAW;SACf,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;SAClE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACvB,SAAS,EAAE,IAAI;QACf,IAAI,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE;KAC/C,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,IAAU;IAEV,MAAM,WAAW,GAAG,MAAM,yBAAyB,EAAE,CAAC;IACtD,OAAO,WAAW;SACf,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;SACtE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACvB,SAAS,EAAE,IAAI;QACf,IAAI,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE;KACnD,CAAC,CAAC,CAAC;AACR,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { Locator, Route } from "playwright";
2
+ import type { NetworkMonitor } from "./networkMonitor.js";
3
+ import type { PopupHandler } from "./popupHandler.js";
4
+ /** Popup definition declared by the POM (what popups exist on this page). */
5
+ export type PopupHandlerDef = {
6
+ /** CSS selector targeting this popup's root element(s). Used by the default
7
+ * CSS-injection popup shield — if provided, popups are hidden via a <style>
8
+ * tag injected by addInitScript instead of reactive addLocatorHandler. */
9
+ readonly cssSelector?: string;
10
+ readonly dismiss: () => Promise<void>;
11
+ readonly name: string;
12
+ readonly trigger: Locator;
13
+ };
14
+ /** Route interceptor declared by the POM. */
15
+ export type RouteInterceptorDef = {
16
+ readonly handler: (route: Route) => Promise<void>;
17
+ readonly name: string;
18
+ readonly pattern: string;
19
+ };
20
+ /** Options passed to entry point create() methods. */
21
+ export type PageSetupOptions = {
22
+ /** Skip these POM-defined popup handlers by name. */
23
+ allowPopups?: string[];
24
+ /** Skip these POM-defined route interceptors by name. */
25
+ allowRoutes?: string[];
26
+ /** Flow-owned popup handler — POM registers its popups through it. */
27
+ handler?: PopupHandler;
28
+ /** Flow-owned network monitor — installed on the page for HTTP error
29
+ * tracking. `null` stays accepted because existing flow code passes
30
+ * `monitor: null` explicitly. */
31
+ monitor?: NetworkMonitor | null;
32
+ permissions?: string[];
33
+ proxy?: {
34
+ password?: string;
35
+ server: string;
36
+ username?: string;
37
+ };
38
+ /** Slow down each Playwright operation by this many ms (debugging aid). */
39
+ slowMo?: number;
40
+ /** Custom URL to navigate to instead of the default. */
41
+ url?: string;
42
+ };
43
+ //# sourceMappingURL=pageHooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageHooks.d.ts","sourceRoot":"","sources":["../src/pageHooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG;IAC5B;;+EAE2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,sDAAsD;AACtD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,sEAAsE;IACtE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;sCAEkC;IAClC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pageHooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageHooks.js","sourceRoot":"","sources":["../src/pageHooks.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Page Registry — central POM construction infrastructure. Stores POM classes
3
+ * keyed by name; `register-pages.ts` calls `registerPage`, `BasePageObject`
4
+ * calls `createPage`, and `EntryPointPageObject.installPageHooks` calls
5
+ * `getRegisteredPopupHandlers` / `getRegisteredRouteInterceptors`.
6
+ *
7
+ * Registration is eager (`registerPage("LoginPage", LoginPage)`) or lazy
8
+ * (`registerPage("LoginPage", () => import("../pages/login-page.ts"))`). A
9
+ * lazy module loads on first use and must export the class under the
10
+ * registered name. Lazy registration keeps the barrel free of value imports.
11
+ */
12
+ import type { Page } from "playwright";
13
+ import type { RegisteredPages } from "./index.js";
14
+ import type { PopupHandlerDef, RouteInterceptorDef } from "./pageHooks.js";
15
+ type RegistrablePage = {
16
+ popupHandlers(): PopupHandlerDef[];
17
+ routeInterceptors(): RouteInterceptorDef[];
18
+ };
19
+ export type PomClass = {
20
+ createFromPage(page: Page): RegistrablePage;
21
+ prototype: RegistrablePage;
22
+ };
23
+ /**
24
+ * Loads the module that exports the registered class, e.g.
25
+ * `() => import("../pages/login-page.ts")`. The module must export the class
26
+ * under the registered `name`; `PomModuleLoader<TName>` ties the two together
27
+ * so a mismatched import — `registerPage("LoginPage", () => import("./other.js"))`
28
+ * — is a compile error.
29
+ */
30
+ export type PomModuleLoader<TName extends string = string> = () => Promise<Record<TName, PomClass>>;
31
+ export type RegisterPageOptions = {
32
+ /**
33
+ * Pass `false` when the POM declares no `popupHandlers()` /
34
+ * `routeInterceptors()` overrides, so page-hook installation can skip
35
+ * loading its module. Omit when unsure — unflagged lazy entries are
36
+ * loaded and inspected at hook-install time, which is always correct.
37
+ */
38
+ providesPageHooks: boolean;
39
+ };
40
+ export type RegistryEntry = {
41
+ cls: PomClass;
42
+ kind: "eager";
43
+ } | {
44
+ kind: "lazy";
45
+ loader: PomModuleLoader;
46
+ loading: Promise<PomClass> | undefined;
47
+ providesPageHooks: boolean | undefined;
48
+ };
49
+ export declare const entries: Record<string, RegistryEntry>;
50
+ export declare function registerPage<TName extends string>(name: TName, classOrLoader: PomClass | PomModuleLoader<TName>, options?: RegisterPageOptions): void;
51
+ export declare function classDeclaresPageHooks(cls: PomClass): boolean;
52
+ export declare function loadPageClass(name: string, entry: Extract<RegistryEntry, {
53
+ kind: "lazy";
54
+ }>): Promise<PomClass>;
55
+ export declare function createPage<TName extends keyof RegisteredPages & string>(name: TName, page: Page): Promise<RegisteredPages[TName]>;
56
+ export declare function createPage<TPageObject = RegistrablePage>(name: string, page: Page): Promise<TPageObject>;
57
+ export {};
58
+ //# sourceMappingURL=pageRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageRegistry.d.ts","sourceRoot":"","sources":["../src/pageRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE3E,KAAK,eAAe,GAAG;IACrB,aAAa,IAAI,eAAe,EAAE,CAAC;IACnC,iBAAiB,IAAI,mBAAmB,EAAE,CAAC;CAC5C,CAAC;AAIF,MAAM,MAAM,QAAQ,GAAG;IACrB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,eAAe,CAAC;IAC5C,SAAS,EAAE,eAAe,CAAC;CAC5B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,OAAO,CACxE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CACxB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB;IAAE,GAAG,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAChC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IACvC,iBAAiB,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC,CAAC;AAEN,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAM,CAAC;AAYzD,wBAAgB,YAAY,CAAC,KAAK,SAAS,MAAM,EAC/C,IAAI,EAAE,KAAK,EACX,aAAa,EAAE,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,EAChD,OAAO,CAAC,EAAE,mBAAmB,GAC5B,IAAI,CAAC;AA+BR,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAK7D;AAyBD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9C,OAAO,CAAC,QAAQ,CAAC,CAgBnB;AAUD,wBAAsB,UAAU,CAAC,KAAK,SAAS,MAAM,eAAe,GAAG,MAAM,EAC3E,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;AACnC,wBAAsB,UAAU,CAAC,WAAW,GAAG,eAAe,EAC5D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,WAAW,CAAC,CAAC"}
@@ -0,0 +1,79 @@
1
+ export const entries = {};
2
+ function isPomClass(value) {
3
+ // Duck-type the static side: a PomClass constructor exposes the
4
+ // `createFromPage` factory, a PomModuleLoader is a plain function without it.
5
+ return (typeof value === "function" &&
6
+ "createFromPage" in value &&
7
+ typeof value.createFromPage === "function");
8
+ }
9
+ export function registerPage(name, classOrLoader, options) {
10
+ if (entries[name])
11
+ throw Error(`Page "${name}" is already registered.`);
12
+ if (isPomClass(classOrLoader)) {
13
+ assertHookFlagMatchesClass(name, options?.providesPageHooks, classOrLoader);
14
+ entries[name] = { cls: classOrLoader, kind: "eager" };
15
+ return;
16
+ }
17
+ entries[name] = {
18
+ kind: "lazy",
19
+ loader: classOrLoader,
20
+ loading: undefined,
21
+ providesPageHooks: options?.providesPageHooks,
22
+ };
23
+ }
24
+ function assertIsPomClass(name, loaded) {
25
+ if (isPomClass(loaded))
26
+ return loaded;
27
+ throw Error(`Lazy registration for page "${name}" did not resolve to a page-object class: ` +
28
+ `the loaded module must export "${name}" extending BasePageObject.`);
29
+ }
30
+ export function classDeclaresPageHooks(cls) {
31
+ return (Object.hasOwn(cls.prototype, "popupHandlers") ||
32
+ Object.hasOwn(cls.prototype, "routeInterceptors"));
33
+ }
34
+ /**
35
+ * `providesPageHooks: false` promises hook installation it can skip loading
36
+ * this module. If the POM declares a `popupHandlers()` /
37
+ * `routeInterceptors()` override anyway, its hooks would silently never
38
+ * install (popups stop being dismissed, with no error). Surface that
39
+ * contradiction as early as possible: at registration for eager classes, on
40
+ * first load for lazy ones.
41
+ */
42
+ function assertHookFlagMatchesClass(name, providesPageHooks, cls) {
43
+ if (providesPageHooks !== false)
44
+ return;
45
+ if (!classDeclaresPageHooks(cls))
46
+ return;
47
+ throw Error(`Page "${name}" was registered with { providesPageHooks: false } but its ` +
48
+ `class declares popupHandlers()/routeInterceptors(). Drop the flag so ` +
49
+ `its page hooks are installed.`);
50
+ }
51
+ export async function loadPageClass(name, entry) {
52
+ entry.loading ??= entry
53
+ .loader()
54
+ .then((moduleNamespace) => {
55
+ const cls = assertIsPomClass(name, moduleNamespace[name]);
56
+ assertHookFlagMatchesClass(name, entry.providesPageHooks, cls);
57
+ return cls;
58
+ })
59
+ .catch((error) => {
60
+ // Never memoize a rejection: a transient loader failure would otherwise
61
+ // poison this page name for the rest of the process. Clearing lets the
62
+ // next createPage / hook-install call retry the import.
63
+ entry.loading = undefined;
64
+ throw error;
65
+ });
66
+ return entry.loading;
67
+ }
68
+ async function resolvePageClass(name) {
69
+ const entry = entries[name];
70
+ if (!entry)
71
+ throw Error(`Unknown page: ${name}. Was register-pages.ts imported?`);
72
+ return entry.kind === "eager" ? entry.cls : loadPageClass(name, entry);
73
+ }
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- implementation of the overloads above
75
+ export async function createPage(name, page) {
76
+ const cls = await resolvePageClass(name);
77
+ return cls.createFromPage(page);
78
+ }
79
+ //# sourceMappingURL=pageRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageRegistry.js","sourceRoot":"","sources":["../src/pageRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Lightweight tRPC HTTP client for the QAW platform API.
3
+ *
4
+ * Used at runtime by getInbox (email polling) and potentially other
5
+ * platform features. Requires QAW_TOKEN env var for authentication.
6
+ */
7
+ export declare function callPlatformAPI<TResponse>(opts: {
8
+ endpoint: string;
9
+ input: Record<string, unknown>;
10
+ }): Promise<TResponse>;
11
+ //# sourceMappingURL=platformClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformClient.d.ts","sourceRoot":"","sources":["../src/platformClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,wBAAsB,eAAe,CAAC,SAAS,EAAE,IAAI,EAAE;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,GAAG,OAAO,CAAC,SAAS,CAAC,CA2BrB"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Lightweight tRPC HTTP client for the QAW platform API.
3
+ *
4
+ * Used at runtime by getInbox (email polling) and potentially other
5
+ * platform features. Requires QAW_TOKEN env var for authentication.
6
+ */
7
+ const BASE_URL = "https://app.qawolf.com/api/trpc";
8
+ export async function callPlatformAPI(opts) {
9
+ const token = process.env.QAW_TOKEN;
10
+ if (!token) {
11
+ throw Error("QAW_TOKEN env var is required for platform API calls. " +
12
+ "Set it in .env or pass it via the environment.");
13
+ }
14
+ const inputJson = JSON.stringify(opts.input);
15
+ const url = `${BASE_URL}/${opts.endpoint}?input=${encodeURIComponent(inputJson)}`;
16
+ const res = await fetch(url, {
17
+ headers: { Authorization: `Bearer ${token}` },
18
+ method: "GET",
19
+ });
20
+ if (!res.ok) {
21
+ throw Error(`Platform API ${opts.endpoint} returned ${res.status}: ${res.statusText}`);
22
+ }
23
+ const body = (await res.json());
24
+ const envelope = body.result?.data || body.data || body;
25
+ return (envelope?.json ?? envelope);
26
+ }
27
+ //# sourceMappingURL=platformClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformClient.js","sourceRoot":"","sources":["../src/platformClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,QAAQ,GAAG,iCAAiC,CAAC;AASnD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAY,IAGhD;IACC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACpC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,CACT,wDAAwD;YACtD,gDAAgD,CACnD,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,IAAI,CAAC,QAAQ,UAAU,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;IAElF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;QAC7C,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,KAAK,CACT,gBAAgB,IAAI,CAAC,QAAQ,aAAa,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;IAExD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;IACxD,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,QAAQ,CAAc,CAAC;AACnD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Locator, Page } from "playwright";
2
+ export declare class PopupHandler {
3
+ readonly name: string;
4
+ /** List all registered popup handler names. */
5
+ get registered(): string[];
6
+ private _page;
7
+ private _registrations;
8
+ constructor(name: string);
9
+ /** Register a popup for auto-dismissal. */
10
+ add(name: string, trigger: Locator, dismiss: () => Promise<void>): Promise<void>;
11
+ /** Check if a popup handler is registered by name. */
12
+ has(name: string): boolean;
13
+ /** Bind to a page. Throws if already bound — one handler per page. */
14
+ install(page: Page): void;
15
+ /** Remove a popup handler by name. */
16
+ remove(name: string): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=popupHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popupHandler.d.ts","sourceRoot":"","sources":["../src/popupHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEhD,qBAAa,YAAY;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,IAAI,UAAU,IAAI,MAAM,EAAE,CAEzB;IACD,OAAO,CAAC,KAAK,CAA+B;IAE5C,OAAO,CAAC,cAAc,CAGlB;gBAEQ,IAAI,EAAE,MAAM;IAIxB,2CAA2C;IACrC,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IAYhB,sDAAsD;IACtD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,sEAAsE;IACtE,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAazB,sCAAsC;IAChC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO1C"}
@@ -0,0 +1,46 @@
1
+ export class PopupHandler {
2
+ name;
3
+ /** List all registered popup handler names. */
4
+ get registered() {
5
+ return [...this._registrations.keys()];
6
+ }
7
+ _page = undefined;
8
+ _registrations = new Map();
9
+ constructor(name) {
10
+ this.name = name;
11
+ }
12
+ /** Register a popup for auto-dismissal. */
13
+ async add(name, trigger, dismiss) {
14
+ if (!this._page) {
15
+ throw Error(`PopupHandler "${this.name}" is not installed on a page yet.`);
16
+ }
17
+ this._registrations.set(name, { dismiss, trigger });
18
+ await this._page.addLocatorHandler(trigger, async () => {
19
+ await dismiss();
20
+ });
21
+ }
22
+ /** Check if a popup handler is registered by name. */
23
+ has(name) {
24
+ return this._registrations.has(name);
25
+ }
26
+ /** Bind to a page. Throws if already bound — one handler per page. */
27
+ install(page) {
28
+ if (this._page) {
29
+ throw Error(`PopupHandler "${this.name}" is already bound to a page. ` +
30
+ `Each handler tracks exactly one page handle. For multi-page ` +
31
+ `sessions, create a separate PopupHandler per page:\n\n` +
32
+ ` const mainPopups = new PopupHandler("main");\n` +
33
+ ` const secondaryPopups = new PopupHandler("secondary");`);
34
+ }
35
+ this._page = page;
36
+ }
37
+ /** Remove a popup handler by name. */
38
+ async remove(name) {
39
+ const reg = this._registrations.get(name);
40
+ if (reg && this._page) {
41
+ await this._page.removeLocatorHandler(reg.trigger);
42
+ this._registrations.delete(name);
43
+ }
44
+ }
45
+ }
46
+ //# sourceMappingURL=popupHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popupHandler.js","sourceRoot":"","sources":["../src/popupHandler.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,YAAY;IACd,IAAI,CAAS;IACtB,+CAA+C;IAC/C,IAAI,UAAU;QACZ,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACO,KAAK,GAAqB,SAAS,CAAC;IAEpC,cAAc,GAAG,IAAI,GAAG,EAG7B,CAAC;IAEJ,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,GAAG,CACP,IAAY,EACZ,OAAgB,EAChB,OAA4B;QAE5B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,KAAK,CACT,iBAAiB,IAAI,CAAC,IAAI,mCAAmC,CAC9D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,sEAAsE;IACtE,OAAO,CAAC,IAAU;QAChB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CACT,iBAAiB,IAAI,CAAC,IAAI,gCAAgC;gBACxD,8DAA8D;gBAC9D,wDAAwD;gBACxD,uDAAuD;gBACvD,0DAA0D,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Build the addInitScript source for the default popup shield.
3
+ *
4
+ * Injects a MutationObserver that hides overlay/popup elements via inline
5
+ * styles. Inline !important always beats stylesheet !important (regardless of
6
+ * specificity or load order), so page CSS can never override this shield.
7
+ * Runs before any page JS on every navigation — deadlock-free, unlike
8
+ * addLocatorHandler (see `EntryPointPageObject.installPageHooks`).
9
+ */
10
+ export declare function buildPopupShieldInitScript(cssSelectors: string[]): string;
11
+ //# sourceMappingURL=popupShieldInitScript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popupShieldInitScript.d.ts","sourceRoot":"","sources":["../src/popupShieldInitScript.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAkCzE"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Build the addInitScript source for the default popup shield.
3
+ *
4
+ * Injects a MutationObserver that hides overlay/popup elements via inline
5
+ * styles. Inline !important always beats stylesheet !important (regardless of
6
+ * specificity or load order), so page CSS can never override this shield.
7
+ * Runs before any page JS on every navigation — deadlock-free, unlike
8
+ * addLocatorHandler (see `EntryPointPageObject.installPageHooks`).
9
+ */
10
+ export function buildPopupShieldInitScript(cssSelectors) {
11
+ const selectorList = cssSelectors.join(", ");
12
+ const escaped = JSON.stringify(selectorList);
13
+ return `
14
+ (function() {
15
+ var SELECTOR = ${escaped};
16
+ function hideMatches() {
17
+ document.querySelectorAll(SELECTOR).forEach(function(el) {
18
+ if (el.dataset.__qawHidden) return;
19
+ el.dataset.__qawHidden = '1';
20
+ el.style.setProperty('display', 'none', 'important');
21
+ el.style.setProperty('pointer-events', 'none', 'important');
22
+ el.style.setProperty('visibility', 'hidden', 'important');
23
+ });
24
+ }
25
+ // Use MutationObserver to hide overlays immediately when they appear.
26
+ // The data-marker prevents re-trigger loops (skip already-hidden elements).
27
+ var observer = new MutationObserver(function(mutations) {
28
+ for (var i = 0; i < mutations.length; i++) {
29
+ if (mutations[i].addedNodes.length > 0) { hideMatches(); return; }
30
+ }
31
+ });
32
+ hideMatches();
33
+ function startObserver() {
34
+ observer.observe(document.documentElement, { childList: true, subtree: true });
35
+ hideMatches();
36
+ }
37
+ if (document.readyState === 'loading') {
38
+ document.addEventListener('DOMContentLoaded', startObserver);
39
+ } else {
40
+ startObserver();
41
+ }
42
+ })();
43
+ `;
44
+ }
45
+ //# sourceMappingURL=popupShieldInitScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popupShieldInitScript.js","sourceRoot":"","sources":["../src/popupShieldInitScript.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CAAC,YAAsB;IAC/D,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC7C,OAAO;;4BAEmB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4B3B,CAAC;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type SequencePromise<TValue> = Promise<TValue>;
2
+ //# sourceMappingURL=sequence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../src/sequence.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sequence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence.js","sourceRoot":"","sources":["../src/sequence.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import { BasePageObject } from "./basePageObject.js";
2
+ /**
3
+ * The `TParent` generic exists for human readability and AST discoverability –
4
+ * tooling can extract every `SubPageObject<X>`, build parent-child graphs, and
5
+ * generate documentation automatically.
6
+ */
7
+ export declare abstract class SubPageObject<TParent extends BasePageObject> extends BasePageObject {
8
+ }
9
+ //# sourceMappingURL=subPageObject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subPageObject.d.ts","sourceRoot":"","sources":["../src/subPageObject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;GAIG;AACH,8BAAsB,aAAa,CAEjC,OAAO,SAAS,cAAc,CAC9B,SAAQ,cAAc;CAAG"}
@@ -0,0 +1,9 @@
1
+ import { BasePageObject } from "./basePageObject.js";
2
+ /**
3
+ * The `TParent` generic exists for human readability and AST discoverability –
4
+ * tooling can extract every `SubPageObject<X>`, build parent-child graphs, and
5
+ * generate documentation automatically.
6
+ */
7
+ export class SubPageObject extends BasePageObject {
8
+ }
9
+ //# sourceMappingURL=subPageObject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subPageObject.js","sourceRoot":"","sources":["../src/subPageObject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;GAIG;AACH,MAAM,OAAgB,aAGpB,SAAQ,cAAc;CAAG"}
@@ -0,0 +1,7 @@
1
+ /** Strip currency symbols and commas, return numeric value. */
2
+ export declare function moneyToNumber(currencyString: string): number;
3
+ /** Format a number back to currency string. */
4
+ export declare function numberToMoney(amount: number, locale?: string, currency?: string): string;
5
+ /** Assert two currency strings are approximately equal. */
6
+ export declare function assertPricesClose(actual: string, expected: string, precision?: number): void;
7
+ //# sourceMappingURL=testDataUtilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testDataUtilities.d.ts","sourceRoot":"","sources":["../src/testDataUtilities.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,SAAU,EAChB,QAAQ,SAAQ,GACf,MAAM,CAIR;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAI,GACZ,IAAI,CAeN"}
@@ -0,0 +1,21 @@
1
+ /** Strip currency symbols and commas, return numeric value. */
2
+ export function moneyToNumber(currencyString) {
3
+ const cleaned = currencyString.replace(/[^0-9.-]/g, "");
4
+ return parseFloat(cleaned);
5
+ }
6
+ /** Format a number back to currency string. */
7
+ export function numberToMoney(amount, locale = "en-US", currency = "USD") {
8
+ return new Intl.NumberFormat(locale, { currency, style: "currency" }).format(amount);
9
+ }
10
+ /** Assert two currency strings are approximately equal. */
11
+ export function assertPricesClose(actual, expected, precision = 2) {
12
+ const actualNum = moneyToNumber(actual);
13
+ const expectedNum = moneyToNumber(expected);
14
+ if (!Number.isFinite(actualNum) || !Number.isFinite(expectedNum)) {
15
+ throw Error(`Invalid price value: ${actual} (${actualNum}) vs ${expected} (${expectedNum})`);
16
+ }
17
+ if (Math.abs(actualNum - expectedNum) > Math.pow(10, -precision)) {
18
+ throw Error(`Prices not close: ${actual} (${actualNum}) vs ${expected} (${expectedNum})`);
19
+ }
20
+ }
21
+ //# sourceMappingURL=testDataUtilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testDataUtilities.js","sourceRoot":"","sources":["../src/testDataUtilities.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,cAAsB;IAClD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,MAAM,GAAG,OAAO,EAChB,QAAQ,GAAG,KAAK;IAEhB,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAC1E,MAAM,CACP,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,QAAgB,EAChB,SAAS,GAAG,CAAC;IAEb,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACjE,MAAM,KAAK,CACT,wBAAwB,MAAM,KAAK,SAAS,QAAQ,QAAQ,KAAK,WAAW,GAAG,CAChF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QACjE,MAAM,KAAK,CACT,qBAAqB,MAAM,KAAK,SAAS,QAAQ,QAAQ,KAAK,WAAW,GAAG,CAC7E,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@qawolf/pom",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "license": "MIT",
6
+ "sideEffects": false,
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "/dist",
16
+ "/LICENSE",
17
+ "/README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "rm -rf ./dist && tsc -p tsconfig.build.json",
21
+ "lint:ci": "npm run lint:non-fixable; NON_FIXABLE_EXIT=$?; npm run lint:fixable && exit $NON_FIXABLE_EXIT",
22
+ "lint:dev": "npm run lint:fixable",
23
+ "lint:fixable": "eslint . --ext cjs,cts,js,jsx,mjs,ts,tsx --fix --quiet && prettier --log-level=warn --write .",
24
+ "lint:non-fixable": "dpdm --exit-code circular:1 --no-tree --no-warning --transform --include='.*' --exclude='/(dist|node_modules)/' '**/*'",
25
+ "prepublishOnly": "npm run build",
26
+ "test": "NODE_OPTIONS=\"--experimental-vm-modules\" NODE_NO_WARNINGS=1 jest",
27
+ "test:watch": "npm run test -- --watch",
28
+ "tsc:check": "tsc"
29
+ },
30
+ "devDependencies": {
31
+ "@qawolf/flows": "*",
32
+ "expect-type": "^0.15.0",
33
+ "playwright": "1.58.2",
34
+ "typescript": "^5.9.3"
35
+ },
36
+ "peerDependencies": {
37
+ "@qawolf/flows": "^0.1.4",
38
+ "playwright": "1.58.2"
39
+ },
40
+ "peerDependenciesMeta": {
41
+ "playwright": {
42
+ "optional": true
43
+ }
44
+ },
45
+ "engines": {
46
+ "node": ">=22.22.0 <25"
47
+ },
48
+ "publishConfig": {
49
+ "access": "public",
50
+ "registry": "https://registry.npmjs.org"
51
+ },
52
+ "nx": {
53
+ "targets": {
54
+ "npm:publish": {}
55
+ }
56
+ }
57
+ }