pw-core 1.2.1 → 1.3.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 (61) hide show
  1. package/README.md +2 -1
  2. package/dist/cli.js +145 -421
  3. package/dist/codegen/action-formatter.d.ts +19 -0
  4. package/dist/codegen/action-formatter.js +160 -0
  5. package/dist/codegen/action-processor.d.ts +23 -0
  6. package/dist/codegen/action-processor.js +112 -0
  7. package/dist/codegen/floating-panel/client.d.ts +14 -1
  8. package/dist/codegen/floating-panel/client.js +20 -25
  9. package/dist/codegen/floating-panel/manager.js +16 -22
  10. package/dist/codegen/generator/action.validator.d.ts +2 -1
  11. package/dist/codegen/generator/action.validator.js +2 -1
  12. package/dist/codegen/generator/candidate-scorer.d.ts +7 -0
  13. package/dist/codegen/generator/candidate-scorer.js +206 -0
  14. package/dist/codegen/generator/dom-scanner.d.ts +39 -0
  15. package/dist/codegen/generator/dom-scanner.js +429 -0
  16. package/dist/codegen/generator/id-stability.d.ts +6 -0
  17. package/dist/codegen/generator/id-stability.js +38 -0
  18. package/dist/codegen/generator/index.d.ts +8 -10
  19. package/dist/codegen/generator/index.js +23 -678
  20. package/dist/codegen/generator/key-builder.d.ts +13 -0
  21. package/dist/codegen/generator/key-builder.js +32 -0
  22. package/dist/codegen/hover-tracker/client.d.ts +5 -0
  23. package/dist/codegen/hover-tracker/client.js +14 -15
  24. package/dist/codegen/hover-tracker/manager.js +2 -6
  25. package/dist/codegen/index.d.ts +9 -32
  26. package/dist/codegen/index.js +9 -1128
  27. package/dist/codegen/key-utils.d.ts +16 -0
  28. package/dist/codegen/key-utils.js +29 -1
  29. package/dist/codegen/project-finder.d.ts +29 -0
  30. package/dist/codegen/project-finder.js +283 -0
  31. package/dist/codegen/registry-matcher.d.ts +27 -0
  32. package/dist/codegen/registry-matcher.js +254 -0
  33. package/dist/codegen/registry-store.d.ts +52 -0
  34. package/dist/codegen/registry-store.js +652 -0
  35. package/dist/codegen/selector-parser.d.ts +16 -0
  36. package/dist/codegen/selector-parser.js +121 -0
  37. package/dist/codegen/types.d.ts +18 -1
  38. package/dist/codegen/uniqueness.d.ts +3 -0
  39. package/dist/codegen/uniqueness.js +15 -0
  40. package/dist/component/table.d.ts +2 -2
  41. package/dist/component/table.js +7 -6
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.js +19 -0
  44. package/dist/page/actions/locator-actions.d.ts +6 -10
  45. package/dist/page/actions/locator-actions.js +24 -23
  46. package/dist/page/assertions/verify-chain.d.ts +11 -13
  47. package/dist/page/assertions/verify-chain.js +26 -7
  48. package/dist/page/assertions/verify-helpers.d.ts +5 -15
  49. package/dist/page/config.d.ts +25 -25
  50. package/dist/page/locators/dynamic-locator-resolver.js +22 -9
  51. package/dist/page/locators/resolver.d.ts +17 -11
  52. package/dist/page/locators/resolver.js +84 -78
  53. package/dist/page/registry.d.ts +35 -35
  54. package/dist/page/registry.js +86 -82
  55. package/dist/page/typed-page.d.ts +1 -0
  56. package/dist/page/typed-page.js +22 -12
  57. package/dist/page/types/proxy-methods.d.ts +11 -19
  58. package/dist/page/types/validation.d.ts +1 -1
  59. package/dist/page/utils/formatter.d.ts +3 -3
  60. package/dist/page/utils/formatter.js +5 -2
  61. package/package.json +6 -3
@@ -1,14 +1,14 @@
1
- import { Locator } from '@playwright/test';
2
- import type { DynamicTestIdEntry, DynamicSelectorEntry } from './locators/dynamic-locator-resolver.js';
3
- export { ProxyLocatorMethods } from './types/proxy-methods.js';
4
- export type { DynamicLocatorEntry, DynamicTestIdEntry, DynamicSelectorEntry } from './locators/dynamic-locator-resolver.js';
5
- import { AllowedMethodKeys } from '../types/methods';
6
- import { StrategyType, LocatorStrategyOptions } from '../types/strategies';
7
- import { ResolvedTestIdKeys, ValidateTestIds } from './types/validation.js';
1
+ import type { Locator } from '@playwright/test';
2
+ import type { DynamicTestIdEntry, DynamicSelectorEntry } from './locators/dynamic-locator-resolver';
3
+ export { ProxyLocatorMethods } from './types/proxy-methods';
4
+ export type { DynamicLocatorEntry, DynamicTestIdEntry, DynamicSelectorEntry } from './locators/dynamic-locator-resolver';
5
+ import type { AllowedMethodKeys } from '../types/methods';
6
+ import type { StrategyType, LocatorStrategyOptions } from '../types/strategies';
7
+ import type { ResolvedTestIdKeys, ValidateTestIds } from './types/validation';
8
8
  export { zeroArgMethodsList, oneArgMethodsList } from '../constants/methods';
9
9
  export { rolesList, strategyList } from '../constants/strategies';
10
- export { AllowedZeroArgMethods, AllowedOneArgMethods, AllowedMethodKeys } from '../types/methods';
11
- export { RoleType, StrategyType, PlaywrightRoleOptions, PlaywrightTextOptions, LocatorStrategyOptions } from '../types/strategies';
10
+ export type { AllowedZeroArgMethods, AllowedOneArgMethods, AllowedMethodKeys } from '../types/methods';
11
+ export type { RoleType, StrategyType, PlaywrightRoleOptions, PlaywrightTextOptions, LocatorStrategyOptions } from '../types/strategies';
12
12
  export type GetStrategyOfKey<T, K extends string> = K extends (T extends {
13
13
  testId: infer I;
14
14
  } ? ResolvedTestIdKeys<I> : never) ? 'testId' : K extends (T extends {
@@ -26,13 +26,13 @@ export type ModifyOptionsForTarget<T, Target, Options> = Options & {
26
26
  } & (Target extends string ? LocatorStrategyOptions<GetStrategyOfKey<T, Target>> : {});
27
27
  export type PageKeys<T> = (T extends {
28
28
  testId: infer I;
29
- } ? (I extends Record<string, any> ? ResolvedTestIdKeys<I> : never) : never) | (T extends {
29
+ } ? (I extends Record<string, unknown> ? ResolvedTestIdKeys<I> : never) : never) | (T extends {
30
30
  testIds: infer I;
31
- } ? (I extends Record<string, any> ? ResolvedTestIdKeys<I> : never) : never) | (T extends {
31
+ } ? (I extends Record<string, unknown> ? ResolvedTestIdKeys<I> : never) : never) | (T extends {
32
32
  selector: infer S;
33
- } ? (S extends Record<string, any> ? ResolvedTestIdKeys<S> : never) : never) | (T extends {
33
+ } ? (S extends Record<string, unknown> ? ResolvedTestIdKeys<S> : never) : never) | (T extends {
34
34
  selectors: infer S;
35
- } ? (S extends Record<string, any> ? ResolvedTestIdKeys<S> : never) : never) | {
35
+ } ? (S extends Record<string, unknown> ? ResolvedTestIdKeys<S> : never) : never) | {
36
36
  [S in Exclude<StrategyType, 'testId' | 'selector'>]: T extends Record<S, readonly string[]> ? T[S][number] : never;
37
37
  }[Exclude<StrategyType, 'testId' | 'selector'>];
38
38
  export type CheckableLocatorKeys<T> = {
@@ -88,43 +88,43 @@ export type KeysOfOtherStrategies<T, S extends StrategyType> = {
88
88
  }[Exclude<StrategyType, S>];
89
89
  type GetTestIds<T> = T extends {
90
90
  testId: infer I;
91
- } ? (I extends Record<string, any> ? I : {}) : T extends {
91
+ } ? (I extends Record<string, unknown> ? I : {}) : T extends {
92
92
  testIds: infer I;
93
- } ? (I extends Record<string, any> ? I : {}) : {};
93
+ } ? (I extends Record<string, unknown> ? I : {}) : {};
94
94
  type GetSelectors<T> = T extends {
95
95
  selector: infer S;
96
- } ? (S extends Record<string, any> ? S : {}) : T extends {
96
+ } ? (S extends Record<string, unknown> ? S : {}) : T extends {
97
97
  selectors: infer S;
98
- } ? (S extends Record<string, any> ? S : {}) : {};
98
+ } ? (S extends Record<string, unknown> ? S : {}) : {};
99
99
  export type ValidatePageConfig<T> = {
100
100
  url?: string;
101
101
  testId?: T extends {
102
102
  testId: infer I;
103
- } ? I extends Record<string, any> ? ValidateTestIds<I, 'testId', GetSelectors<T>> & {
103
+ } ? I extends Record<string, unknown> ? ValidateTestIds<I, 'testId', GetSelectors<T>> & {
104
104
  [K in keyof I]: K extends KeysOfOtherStrategies<T, 'testId'> ? {
105
105
  [P in `Error: Duplicate key "${K & string}" is defined in multiple strategies`]: never;
106
- } : any;
106
+ } : unknown;
107
107
  } : TestIdMap : TestIdMap;
108
108
  testIds?: T extends {
109
109
  testIds: infer I;
110
- } ? I extends Record<string, any> ? ValidateTestIds<I, 'testId', GetSelectors<T>> & {
110
+ } ? I extends Record<string, unknown> ? ValidateTestIds<I, 'testId', GetSelectors<T>> & {
111
111
  [K in keyof I]: K extends KeysOfOtherStrategies<T, 'testId'> ? {
112
112
  [P in `Error: Duplicate key "${K & string}" is defined in multiple strategies`]: never;
113
- } : any;
113
+ } : unknown;
114
114
  } : TestIdMap : TestIdMap;
115
115
  selector?: T extends {
116
116
  selector: infer S;
117
- } ? S extends Record<string, any> ? ValidateTestIds<S, 'selector', GetTestIds<T>> & {
117
+ } ? S extends Record<string, unknown> ? ValidateTestIds<S, 'selector', GetTestIds<T>> & {
118
118
  [K in keyof S]: K extends KeysOfOtherStrategies<T, 'selector'> ? {
119
119
  [P in `Error: Duplicate key "${K & string}" is defined in multiple strategies`]: never;
120
- } : any;
120
+ } : unknown;
121
121
  } : SelectorMap : SelectorMap;
122
122
  selectors?: T extends {
123
123
  selectors: infer S;
124
- } ? S extends Record<string, any> ? ValidateTestIds<S, 'selector', GetTestIds<T>> & {
124
+ } ? S extends Record<string, unknown> ? ValidateTestIds<S, 'selector', GetTestIds<T>> & {
125
125
  [K in keyof S]: K extends KeysOfOtherStrategies<T, 'selector'> ? {
126
126
  [P in `Error: Duplicate key "${K & string}" is defined in multiple strategies`]: never;
127
- } : any;
127
+ } : unknown;
128
128
  } : SelectorMap : SelectorMap;
129
129
  } & {
130
130
  [S in Exclude<StrategyType, 'testId' | 'selector'>]?: T extends Record<S, infer A> ? A extends readonly string[] ? {
@@ -63,6 +63,24 @@ function extractPlaceholders(pattern) {
63
63
  }
64
64
  return names;
65
65
  }
66
+ function getPlaceholderValues(entry) {
67
+ const placeholders = {};
68
+ for (const [key, value] of Object.entries(entry)) {
69
+ if (key !== 'testId' && key !== 'selector') {
70
+ placeholders[key] = value;
71
+ }
72
+ }
73
+ return placeholders;
74
+ }
75
+ function collectPlaceholderArrays(placeholders, names) {
76
+ return names.map((name) => {
77
+ const value = placeholders[name];
78
+ if (!Array.isArray(value)) {
79
+ throw new Error(`Dynamic locator placeholder "${name}" must be an array.`);
80
+ }
81
+ return value;
82
+ });
83
+ }
66
84
  /**
67
85
  * Expand a single dynamic key pattern + entry into flat key → locator-value pairs.
68
86
  * Validates the entry at runtime before expansion.
@@ -71,14 +89,12 @@ function extractPlaceholders(pattern) {
71
89
  function expandSingleDynamic(pattern, entry) {
72
90
  const testIdPattern = entry.testId;
73
91
  const selectorPattern = entry.selector;
74
- const targetPattern = (testIdPattern !== undefined ? testIdPattern : selectorPattern);
75
- const targetKey = testIdPattern !== undefined ? 'testId' : 'selector';
92
+ const targetPattern = (testIdPattern ?? selectorPattern);
76
93
  if (targetPattern === undefined) {
77
94
  throw new Error(`Dynamic locator "${pattern}": entry must contain either 'testId' or 'selector' property.`);
78
95
  }
79
- const placeholders = { ...entry };
80
- delete placeholders.testId;
81
- delete placeholders.selector;
96
+ const targetKey = testIdPattern !== undefined ? 'testId' : 'selector';
97
+ const placeholders = getPlaceholderValues(entry);
82
98
  // ─── Validation ──────────────────────────────────────────────────────
83
99
  const expectedNames = extractPlaceholders(pattern);
84
100
  // 0.5. No duplicate placeholders in the pattern
@@ -114,10 +130,7 @@ function expandSingleDynamic(pattern, entry) {
114
130
  // ─── Expansion ───────────────────────────────────────────────────────
115
131
  // Sort placeholder names longest-first to avoid substring replacement issues
116
132
  const names = Object.keys(placeholders).sort((a, b) => b.length - a.length);
117
- const values = names.map((name) => {
118
- const v = placeholders[name];
119
- return v;
120
- });
133
+ const values = collectPlaceholderArrays(placeholders, names);
121
134
  const result = {};
122
135
  for (const combo of cartesianProduct(values)) {
123
136
  // Build the *key* — replace {name} with Capitalize(value), then uncapitalize the first char
@@ -1,25 +1,31 @@
1
1
  import { Page, Locator } from '@playwright/test';
2
- export declare const locatorStrategies: Record<string, {
2
+ import { PageConfig, StrategyType } from '../config';
3
+ export interface LocatorStrategyDefinition {
3
4
  resolver: string;
4
5
  role?: string;
5
- }>;
6
+ }
7
+ export declare const locatorStrategies: Record<string, LocatorStrategyDefinition>;
6
8
  export interface LocatorMetadata {
7
- strategy: string;
8
- value: any;
9
+ strategy: StrategyType;
10
+ value: string;
9
11
  }
10
- export declare function cleanKey(s: string): string;
11
- export declare const lookupIndexCache: WeakMap<object, Map<string, LocatorMetadata>>;
12
- export declare function buildLookupIndex(config: any): Map<string, LocatorMetadata>;
13
- export declare function defineLocators(instance: any, context: Page | Locator, config: any): void;
14
- export declare function resolveLocator(context: Page | Locator, config: any, target: any, options?: {
12
+ /** A configured locator key or a raw Playwright locator. */
13
+ export type LocatorTarget = string | Locator;
14
+ /** Shared internal options understood by locator resolution. */
15
+ export type LocatorResolutionOptions = {
15
16
  nth?: number;
16
17
  raw?: boolean;
17
18
  hasText?: string | RegExp;
18
- } & Record<string, any>): Locator;
19
+ } & Record<string, unknown>;
20
+ export declare function cleanKey(s: string): string;
21
+ export declare const lookupIndexCache: WeakMap<object, Map<string, LocatorMetadata>>;
22
+ export declare function buildLookupIndex(config: PageConfig): Map<string, LocatorMetadata>;
23
+ export declare function defineLocators(instance: object, context: Page | Locator, config: PageConfig): void;
24
+ export declare function resolveLocator(context: Page | Locator, config: PageConfig, target: LocatorTarget, options?: LocatorResolutionOptions): Locator;
19
25
  /**
20
26
  * Resolve a config key to a proxied Locator with step-wrapped Playwright methods.
21
27
  */
22
- export declare function locator(context: Page | Locator, config: any, target: any, options?: Parameters<Locator['filter']>[0] & {
28
+ export declare function locator(context: Page | Locator, config: PageConfig, target: LocatorTarget, options?: Parameters<Locator['filter']>[0] & {
23
29
  nth?: number;
24
30
  }): Locator;
25
31
  export declare function wrapLocatorWithProxy(loc: Locator): Locator;
@@ -21,13 +21,27 @@ exports.locatorStrategies = {
21
21
  placeholder: { resolver: 'getByPlaceholder' },
22
22
  altText: { resolver: 'getByAltText' }
23
23
  };
24
- // Add all roles dynamically
25
24
  for (const role of config_1.rolesList) {
26
25
  exports.locatorStrategies[role] = { resolver: 'getByRole', role };
27
26
  }
28
27
  function cleanKey(s) {
29
28
  let clean = s;
30
- const suffixes = ['Btn', 'Button', 'Link', 'Input', 'Checkbox', 'Option', 'Title', 'Label', 'Value', 'Text', 'Wrapper', 'Container', 'Card', 'Item'];
29
+ const suffixes = [
30
+ 'Btn',
31
+ 'Button',
32
+ 'Link',
33
+ 'Input',
34
+ 'Checkbox',
35
+ 'Option',
36
+ 'Title',
37
+ 'Label',
38
+ 'Value',
39
+ 'Text',
40
+ 'Wrapper',
41
+ 'Container',
42
+ 'Card',
43
+ 'Item'
44
+ ];
31
45
  for (const suffix of suffixes) {
32
46
  clean = clean.replace(new RegExp(`[-_]?${suffix}$`, 'i'), '');
33
47
  }
@@ -36,6 +50,14 @@ function cleanKey(s) {
36
50
  return clean;
37
51
  }
38
52
  exports.lookupIndexCache = new WeakMap();
53
+ function getLookupIndex(config) {
54
+ let index = exports.lookupIndexCache.get(config);
55
+ if (!index) {
56
+ index = buildLookupIndex(config);
57
+ exports.lookupIndexCache.set(config, index);
58
+ }
59
+ return index;
60
+ }
39
61
  function buildLookupIndex(config) {
40
62
  const index = new Map();
41
63
  const seenInStrategies = new Map();
@@ -90,11 +112,7 @@ function buildLookupIndex(config) {
90
112
  return index;
91
113
  }
92
114
  function defineLocators(instance, context, config) {
93
- let index = exports.lookupIndexCache.get(config);
94
- if (!index) {
95
- index = buildLookupIndex(config);
96
- exports.lookupIndexCache.set(config, index);
97
- }
115
+ const index = getLookupIndex(config);
98
116
  for (const key of index.keys()) {
99
117
  Object.defineProperty(instance, key, {
100
118
  get: () => {
@@ -105,19 +123,63 @@ function defineLocators(instance, context, config) {
105
123
  });
106
124
  }
107
125
  }
108
- function resolveLocator(context, config, target, options) {
109
- if (typeof target !== 'string')
110
- return target;
111
- const targetStr = target;
112
- let index = exports.lookupIndexCache.get(config);
113
- if (!index) {
114
- index = buildLookupIndex(config);
115
- exports.lookupIndexCache.set(config, index);
116
- }
126
+ function resolvePlaywrightLocator(ctx, resolver, role, value, options) {
117
127
  const toRegex = (val) => {
118
128
  const escaped = val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
119
129
  return new RegExp(escaped.replace(/\s+/g, '\\s+'), 'i');
120
130
  };
131
+ if (resolver === 'getByRole') {
132
+ const val = typeof value === 'string' ? toRegex(value) : value;
133
+ const roleOptions = { name: val };
134
+ if (options) {
135
+ const allowedOptions = [
136
+ 'exact',
137
+ 'checked',
138
+ 'disabled',
139
+ 'expanded',
140
+ 'includeHidden',
141
+ 'level',
142
+ 'pressed',
143
+ 'selected'
144
+ ];
145
+ for (const opt of allowedOptions) {
146
+ if (opt in options && options[opt] !== undefined) {
147
+ roleOptions[opt] = options[opt];
148
+ }
149
+ }
150
+ }
151
+ return ctx.getByRole(role, roleOptions);
152
+ }
153
+ if (resolver === 'locator') {
154
+ return ctx.locator(value);
155
+ }
156
+ const opt = {};
157
+ if (options && 'exact' in options && typeof options.exact === 'boolean') {
158
+ opt.exact = options.exact;
159
+ }
160
+ const val = typeof value === 'string' ? toRegex(value) : value;
161
+ switch (resolver) {
162
+ case 'getByTestId':
163
+ return ctx.getByTestId(val);
164
+ case 'getByLabel':
165
+ return ctx.getByLabel(val, opt);
166
+ case 'getByPlaceholder':
167
+ return ctx.getByPlaceholder(val, opt);
168
+ case 'getByAltText':
169
+ return ctx.getByAltText(val, opt);
170
+ case 'getByTitle':
171
+ return ctx.getByTitle(val, opt);
172
+ case 'getByText':
173
+ return ctx.getByText(val, opt);
174
+ default:
175
+ return typeof val === 'string' ? ctx.locator(val) : ctx.getByText(val, opt);
176
+ }
177
+ }
178
+ function resolveLocator(context, config, target, options) {
179
+ if (typeof target !== 'string')
180
+ return target;
181
+ const targetStr = target;
182
+ const index = getLookupIndex(config);
121
183
  const resolveSingle = (key, ctx) => {
122
184
  const cleaned = cleanKey(key);
123
185
  const meta = index.get(cleaned);
@@ -129,30 +191,7 @@ function resolveLocator(context, config, target, options) {
129
191
  throw new Error(`Unknown locator strategy '${meta.strategy}' for key '${key}'.`);
130
192
  }
131
193
  const { resolver, role } = strategy;
132
- if (resolver === 'getByRole') {
133
- const val = typeof meta.value === 'string' ? toRegex(meta.value) : meta.value;
134
- const roleOptions = { name: val };
135
- if (options) {
136
- const allowedOptions = ['exact', 'checked', 'disabled', 'expanded', 'includeHidden', 'level', 'pressed', 'selected'];
137
- for (const opt of allowedOptions) {
138
- if (opt in options) {
139
- roleOptions[opt] = options[opt];
140
- }
141
- }
142
- }
143
- return ctx[resolver](role, roleOptions);
144
- }
145
- else if (resolver === 'locator') {
146
- return ctx[resolver](meta.value);
147
- }
148
- else {
149
- const opt = {};
150
- if (options && 'exact' in options) {
151
- opt.exact = options.exact;
152
- }
153
- const val = typeof meta.value === 'string' ? toRegex(meta.value) : meta.value;
154
- return ctx[resolver](val, opt);
155
- }
194
+ return resolvePlaywrightLocator(ctx, resolver, role, meta.value, options);
156
195
  };
157
196
  let loc;
158
197
  const cleanedTarget = cleanKey(targetStr);
@@ -192,50 +231,17 @@ function locator(context, config, target, options) {
192
231
  : filtered;
193
232
  return wrapLocatorWithProxy(loc);
194
233
  }
234
+ const ACTION_METHODS = new Set([...config_1.zeroArgMethodsList, ...config_1.oneArgMethodsList]);
195
235
  function wrapLocatorWithProxy(loc) {
196
- const actionMethods = [...config_1.zeroArgMethodsList, ...config_1.oneArgMethodsList];
197
236
  return new Proxy(loc, {
198
237
  get: (targetLoc, propKey, receiver) => {
199
238
  const val = Reflect.get(targetLoc, propKey, receiver);
200
- if (typeof val === 'function' && actionMethods.includes(propKey)) {
239
+ if (typeof val === 'function' && typeof propKey === 'string' && ACTION_METHODS.has(propKey)) {
201
240
  return (...args) => {
202
241
  const stepName = (0, formatter_1.formatStepDescription)(propKey, targetLoc, args);
203
- if (propKey === 'fill') {
204
- const options = args[1];
205
- let shouldMask = false;
206
- if (options && typeof options === 'object' && options.mask !== undefined) {
207
- shouldMask = options.mask === true;
208
- }
209
- else {
210
- const targetStr = (0, formatter_1.formatTarget)(targetLoc);
211
- const targetStrLower = targetStr.toLowerCase();
212
- shouldMask = targetStrLower.includes('pass') || targetStrLower.includes('pw');
213
- }
214
- if (shouldMask) {
215
- return test_1.test.step(stepName, async () => {
216
- await targetLoc.focus();
217
- await targetLoc.evaluate((el, val) => {
218
- const inputEl = el;
219
- const prototype = el.tagName === 'TEXTAREA'
220
- ? window.HTMLTextAreaElement.prototype
221
- : window.HTMLInputElement.prototype;
222
- const descriptor = Object.getOwnPropertyDescriptor(prototype, 'value');
223
- if (descriptor && descriptor.set) {
224
- descriptor.set.call(inputEl, val);
225
- }
226
- else {
227
- inputEl.value = val;
228
- }
229
- inputEl.dispatchEvent(new Event('input', { bubbles: true }));
230
- inputEl.dispatchEvent(new Event('change', { bubbles: true }));
231
- }, args[0]);
232
- }, { box: true, location: (0, caller_location_1.getCallerLocation)() });
233
- }
234
- }
235
- return test_1.test.step(stepName, () => val.apply(targetLoc, args), {
236
- box: true,
237
- location: (0, caller_location_1.getCallerLocation)()
238
- });
242
+ return test_1.test.step(stepName, async () => {
243
+ return await targetLoc[propKey](...args);
244
+ }, { box: true, location: (0, caller_location_1.getCallerLocation)() });
239
245
  };
240
246
  }
241
247
  return val;
@@ -5,12 +5,12 @@ export type PageRegistry = Record<string, PageConfig>;
5
5
  export interface PageConstructor<C extends PageConfig> {
6
6
  new (page: Page): TypedPage<C>;
7
7
  }
8
- export type PageRegistryTest<T extends Record<string, PageConfig>, P, W, O = {}> = TestType<P & {
9
- [K in keyof T]: K extends keyof O ? O[K] extends new (page: Page, ...args: any[]) => infer R ? R : TypedPage<T[K]> : TypedPage<T[K]>;
8
+ export type PageRegistryTest<T extends Record<string, PageConfig>, P extends {}, W extends {}, O = {}> = TestType<P & {
9
+ [K in keyof T]: K extends keyof O ? O[K] extends new (page: Page, ...args: unknown[]) => infer R ? R : TypedPage<T[K]> : TypedPage<T[K]>;
10
10
  } & {
11
- [K in keyof T as K extends `worker${infer R}` ? Uncapitalize<R> : never]: K extends keyof O ? O[K] extends new (page: Page, ...args: any[]) => infer R ? R : TypedPage<T[K]> : TypedPage<T[K]>;
11
+ [K in keyof T as K extends `worker${infer R}` ? Uncapitalize<R> : never]: K extends keyof O ? O[K] extends new (page: Page, ...args: unknown[]) => infer R ? R : TypedPage<T[K]> : TypedPage<T[K]>;
12
12
  }, W & {
13
- [K in keyof T as K extends `worker${string}` ? K : `worker${Capitalize<K & string>}`]: K extends keyof O ? O[K] extends new (page: Page, ...args: any[]) => infer R ? R : TypedPage<T[K]> : TypedPage<T[K]>;
13
+ [K in keyof T as K extends `worker${string}` ? K : `worker${Capitalize<K & string>}`]: K extends keyof O ? O[K] extends new (page: Page, ...args: unknown[]) => infer R ? R : TypedPage<T[K]> : TypedPage<T[K]>;
14
14
  } & {
15
15
  workerPage: Page;
16
16
  }> & {
@@ -29,8 +29,8 @@ export type PageRegistryTest<T extends Record<string, PageConfig>, P, W, O = {}>
29
29
  [K in keyof T as K extends `worker${string}` ? K : `worker${Capitalize<K & string>}`]: K extends keyof O ? O[K] : PageConstructor<T[K]>;
30
30
  };
31
31
  extend<O2 extends Partial<{
32
- [K in keyof T]: new (page: Page, ...args: any[]) => any;
33
- }>, B extends TestType<any, any> = typeof test>(overrides: O2, base?: B): B extends TestType<infer BaseP, infer BaseW> ? PageRegistryTest<T, BaseP, BaseW, O2> : never;
32
+ [K in keyof T]: new (page: Page, ...args: unknown[]) => unknown;
33
+ }>, CustomP extends {} = typeof test extends TestType<infer DefaultP, infer _DefaultW> ? DefaultP : {}, CustomW extends {} = typeof test extends TestType<infer _DefaultP, infer DefaultW> ? DefaultW : {}>(overrides: O2, base?: TestType<CustomP, CustomW>): PageRegistryTest<T, CustomP, CustomW, O2>;
34
34
  };
35
35
  /**
36
36
  * Creates a page registry that registers page objects as Playwright fixtures,
@@ -43,35 +43,35 @@ export type PageRegistryTest<T extends Record<string, PageConfig>, P, W, O = {}>
43
43
  *
44
44
  * // returns the extended test runner directly
45
45
  * const test = createPageRegistry({
46
- codegenPage: {
47
- url: '/',
48
- selectors: {
49
- '{item}': {
50
- item: ['why-pw-core', 'why-not-playwright', 'registry', 'typed-page', 'features'],
51
- selector: '[data-parent-id="{item}"]'
52
- },
53
- copyToClipboardBtn: '.page',
54
- dynamicLocators: 'text="Dynamic Locators" >> nth=0',
55
- rootrailthumbright: '#rootRailThumbRight',
56
- 'text{item}': {
57
- item: ['Auto Steps', 'Capabilities >> nth=0', 'Secret Masking'],
58
- selector: 'text="{item}"'
59
- },
60
- tshirts: '.title-title',
61
- tShirts: 'internal:role=link[name="T-Shirts"s]'
62
- },
63
- testIds: {
64
- qaWorkspaceBtn: 'active-workspace-btn',
65
- wsOptionApp: 'ws-option-app'
66
- }
67
- },
68
- blankPage: {
69
- url: '/',
70
- selectors: {
71
- element: '[data-pw-cursor="pointer"]'
72
- }
73
- }
74
- });
46
+ codegenPage: {
47
+ url: '/',
48
+ selectors: {
49
+ '{item}': {
50
+ item: ['why-pw-core', 'why-not-playwright', 'registry', 'typed-page', 'features'],
51
+ selector: '[data-parent-id="{item}"]'
52
+ },
53
+ copyToClipboardBtn: '.page',
54
+ dynamicLocators: 'text="Dynamic Locators" >> nth=0',
55
+ rootrailthumbright: '#rootRailThumbRight',
56
+ 'text{item}': {
57
+ item: ['Auto Steps', 'Capabilities >> nth=0', 'Secret Masking'],
58
+ selector: 'text="{item}"'
59
+ },
60
+ tshirts: '.title-title',
61
+ tShirts: 'internal:role=link[name="T-Shirts"s]'
62
+ },
63
+ testIds: {
64
+ qaWorkspaceBtn: 'active-workspace-btn',
65
+ wsOptionApp: 'ws-option-app'
66
+ }
67
+ },
68
+ blankPage: {
69
+ url: '/',
70
+ selectors: {
71
+ element: '[data-pw-cursor="pointer"]'
72
+ }
73
+ }
74
+ });
75
75
  *
76
76
  * // returns page classes only when accessing .pages
77
77
  * const pages = createPageRegistry({