pw-core 1.1.0 → 1.2.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 (96) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +777 -0
  4. package/dist/codegen/config/context-weights.d.ts +8 -0
  5. package/dist/codegen/config/context-weights.js +11 -0
  6. package/dist/codegen/config/ignored-attributes.d.ts +1 -0
  7. package/dist/codegen/config/ignored-attributes.js +4 -0
  8. package/dist/codegen/config/ignored-classes.d.ts +1 -0
  9. package/dist/codegen/config/ignored-classes.js +144 -0
  10. package/dist/codegen/config/ignored-values.d.ts +1 -0
  11. package/dist/codegen/config/ignored-values.js +4 -0
  12. package/dist/codegen/config/index.d.ts +29 -0
  13. package/dist/codegen/config/index.js +17 -0
  14. package/dist/codegen/config/strategy-order.d.ts +1 -0
  15. package/dist/codegen/config/strategy-order.js +18 -0
  16. package/dist/codegen/config/weights.d.ts +15 -0
  17. package/dist/codegen/config/weights.js +18 -0
  18. package/dist/codegen/floating-panel/client.d.ts +1 -0
  19. package/dist/codegen/floating-panel/client.js +248 -0
  20. package/dist/codegen/floating-panel/index.d.ts +4 -0
  21. package/dist/codegen/floating-panel/index.js +20 -0
  22. package/dist/codegen/floating-panel/manager.d.ts +19 -0
  23. package/dist/codegen/floating-panel/manager.js +90 -0
  24. package/dist/codegen/floating-panel/template.d.ts +2 -0
  25. package/dist/codegen/floating-panel/template.js +58 -0
  26. package/dist/codegen/floating-panel/types.d.ts +7 -0
  27. package/dist/codegen/floating-panel/types.js +2 -0
  28. package/dist/codegen/generator/action.validator.d.ts +5 -0
  29. package/dist/codegen/generator/action.validator.js +27 -0
  30. package/dist/codegen/generator/index.d.ts +13 -0
  31. package/dist/codegen/generator/index.js +724 -0
  32. package/dist/codegen/generator/locator.restricted.d.ts +36 -0
  33. package/dist/codegen/generator/locator.restricted.js +127 -0
  34. package/dist/codegen/generator/locator.validator.d.ts +8 -0
  35. package/dist/codegen/generator/locator.validator.js +38 -0
  36. package/dist/codegen/hover-tracker/client.d.ts +1 -0
  37. package/dist/codegen/hover-tracker/client.js +75 -0
  38. package/dist/codegen/hover-tracker/index.d.ts +3 -0
  39. package/dist/codegen/hover-tracker/index.js +19 -0
  40. package/dist/codegen/hover-tracker/manager.d.ts +11 -0
  41. package/dist/codegen/hover-tracker/manager.js +28 -0
  42. package/dist/codegen/hover-tracker/types.d.ts +3 -0
  43. package/dist/codegen/hover-tracker/types.js +2 -0
  44. package/dist/codegen/index.d.ts +35 -0
  45. package/dist/codegen/index.js +1147 -0
  46. package/dist/codegen/key-utils.d.ts +23 -0
  47. package/dist/codegen/key-utils.js +68 -0
  48. package/dist/codegen/scorer/base-score.d.ts +1 -0
  49. package/dist/codegen/scorer/base-score.js +7 -0
  50. package/dist/codegen/scorer/context-score.d.ts +2 -0
  51. package/dist/codegen/scorer/context-score.js +27 -0
  52. package/dist/codegen/scorer/index.d.ts +5 -0
  53. package/dist/codegen/scorer/index.js +23 -0
  54. package/dist/codegen/scorer/locator.ranking.d.ts +15 -0
  55. package/dist/codegen/scorer/locator.ranking.js +83 -0
  56. package/dist/codegen/scorer/semantic-score.d.ts +1 -0
  57. package/dist/codegen/scorer/semantic-score.js +47 -0
  58. package/dist/codegen/types.d.ts +35 -0
  59. package/dist/codegen/types.js +2 -0
  60. package/dist/component/table.js +19 -14
  61. package/dist/constants/methods.d.ts +2 -0
  62. package/dist/constants/methods.js +33 -0
  63. package/dist/constants/strategies.d.ts +2 -0
  64. package/dist/constants/strategies.js +47 -0
  65. package/dist/helpers.d.ts +1 -1
  66. package/dist/helpers.js +21 -9
  67. package/dist/page/actions/locator-actions.js +46 -2
  68. package/dist/page/actions/page-actions.d.ts +11 -6
  69. package/dist/page/actions/page-actions.js +12 -12
  70. package/dist/page/assertions/verify-chain.d.ts +39 -32
  71. package/dist/page/assertions/verify-chain.js +21 -6
  72. package/dist/page/assertions/verify-helpers.d.ts +9 -3
  73. package/dist/page/assertions/verify-helpers.js +18 -9
  74. package/dist/page/config.d.ts +126 -38
  75. package/dist/page/config.js +10 -31
  76. package/dist/page/index.d.ts +1 -0
  77. package/dist/page/index.js +1 -0
  78. package/dist/page/locators/dynamic-locator-resolver.d.ts +49 -0
  79. package/dist/page/locators/dynamic-locator-resolver.js +187 -0
  80. package/dist/page/locators/resolver.d.ts +15 -14
  81. package/dist/page/locators/resolver.js +187 -30
  82. package/dist/page/registry.d.ts +51 -12
  83. package/dist/page/registry.js +90 -18
  84. package/dist/page/typed-page.d.ts +33 -28
  85. package/dist/page/typed-page.js +89 -12
  86. package/dist/page/types/proxy-methods.d.ts +69 -54
  87. package/dist/page/types/validation.d.ts +69 -0
  88. package/dist/page/types/validation.js +2 -0
  89. package/dist/page/utils/caller-location.d.ts +5 -0
  90. package/dist/page/utils/caller-location.js +82 -0
  91. package/dist/page/utils/formatter.js +14 -4
  92. package/dist/types/methods.d.ts +4 -0
  93. package/dist/types/methods.js +2 -0
  94. package/dist/types/strategies.d.ts +17 -0
  95. package/dist/types/strategies.js +2 -0
  96. package/package.json +8 -1
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Extracts placeholder names from a `{name}` pattern string.
3
+ */
4
+ export type ExtractPlaceholders<S extends string> = S extends `${string}{${infer Name}}${infer Rest}` ? Name | ExtractPlaceholders<Rest> : never;
5
+ /**
6
+ * Checks recursively if a pattern string contains duplicate placeholders.
7
+ */
8
+ export type HasDuplicatePlaceholders<S extends string, Seen extends string = never> = S extends `${string}{${infer Name}}${infer Rest}` ? Name extends Seen ? true : HasDuplicatePlaceholders<Rest, Seen | Name> : false;
9
+ /**
10
+ * Returns the subset of `Placeholders` whose names are NOT found as
11
+ * substrings of `TestId`. Evaluates to `never` when all are present.
12
+ */
13
+ export type MissingInTestId<TestId extends string, Placeholders extends string> = Placeholders extends any ? TestId extends `${string}${Placeholders}${string}` ? never : Placeholders : never;
14
+ /**
15
+ * Validates a dynamic entry by mapping each of its properties to their expected types.
16
+ *
17
+ * By checking properties individually, TypeScript reports the error exactly on the offending line
18
+ * (e.g. on the wrong value or unknown key) instead of marking the entire object as invalid.
19
+ */
20
+ export type ValidateDynamicEntryProperties<Pattern extends string, Entry, TargetKey extends 'testId' | 'selector'> = {
21
+ [Key in keyof Entry | ExtractPlaceholders<Pattern> | TargetKey]: Key extends TargetKey ? Entry extends Record<TargetKey, infer TPat> ? TPat extends string ? [MissingInTestId<TPat, ExtractPlaceholders<Pattern>>] extends [never] ? [Exclude<ExtractPlaceholders<TPat>, ExtractPlaceholders<Pattern>>] extends [never] ? string : {
22
+ [P in `Error: ${TargetKey} contains unknown placeholder(s): ${Exclude<ExtractPlaceholders<TPat>, ExtractPlaceholders<Pattern>> & string}`]: never;
23
+ } : {
24
+ [P in `Error: ${TargetKey} must contain all placeholder names: missing ${MissingInTestId<TPat, ExtractPlaceholders<Pattern>> & string}`]: never;
25
+ } : {
26
+ [P in `Error: ${TargetKey} must be a string`]: never;
27
+ } : {
28
+ [P in `Error: Dynamic entry must include a ${TargetKey} property`]: never;
29
+ } : Key extends ExtractPlaceholders<Pattern> ? Key extends keyof Entry ? Entry[Key] extends readonly string[] ? readonly string[] : {
30
+ [P in `Error: Placeholder key must be an array: ${Key & string}`]: never;
31
+ } : {
32
+ [P in `Error: Missing placeholder key: ${Key & string}`]: never;
33
+ } : {
34
+ [P in `Error: Only placeholder keys and '${TargetKey}' are allowed`]: never;
35
+ };
36
+ };
37
+ /**
38
+ * Replaces every `{Name}` placeholder in `Pattern` with `Capitalize<Value>`
39
+ * where `Value` is drawn from the corresponding array in `Entry`.
40
+ * Template-literal unions distribute automatically, producing the full cartesian product.
41
+ */
42
+ export type ReplacePattern<Pattern extends string, Entry> = Pattern extends `${infer Before}{${infer Name}}${infer After}` ? Name extends keyof Entry ? Entry[Name] extends readonly string[] ? `${Before}${Capitalize<Entry[Name][number]>}${ReplacePattern<After, Entry> & string}` : never : never : Pattern;
43
+ /**
44
+ * Expands a dynamic key pattern into the union of all concrete (camelCased) keys.
45
+ */
46
+ export type ExpandDynamicKey<Pattern extends string, Entry> = Uncapitalize<ReplacePattern<Pattern, Entry>>;
47
+ /**
48
+ * Resolves every key in a testIds record:
49
+ * - string values → the key itself (static locator)
50
+ * - object values → the expanded dynamic key union
51
+ */
52
+ export type ResolvedTestIdKeys<I> = {
53
+ [K in keyof I & string]: I[K] extends string ? K : ExpandDynamicKey<K, I[K]>;
54
+ }[keyof I & string];
55
+ export type AllExpandedTestIdKeys<I> = {
56
+ [P in keyof I & string]: I[P] extends string ? P : ExpandDynamicKey<P, I[P]>;
57
+ }[keyof I & string];
58
+ export type AllOtherExpandedTestIdKeys<I, K extends keyof I> = {
59
+ [P in Exclude<keyof I, K> & string]: I[P] extends string ? P : ExpandDynamicKey<P, I[P]>;
60
+ }[Exclude<keyof I, K> & string];
61
+ export type ValidateTestIds<I, TargetKey extends 'testId' | 'selector', S> = {
62
+ [K in keyof I & string]: I[K] extends string ? K extends AllOtherExpandedTestIdKeys<I, K> | AllExpandedTestIdKeys<S> ? {
63
+ [P in `Error: Duplicate key "${K}" is defined in multiple entries`]: never;
64
+ } : string : ExpandDynamicKey<K, I[K]> & (AllOtherExpandedTestIdKeys<I, K> | AllExpandedTestIdKeys<S>) extends never ? K extends `${string}{${string}}${string}` ? HasDuplicatePlaceholders<K> extends true ? {
65
+ [P in 'Error: Pattern contains duplicate placeholders']: never;
66
+ } : ValidateDynamicEntryProperties<K, I[K], TargetKey> : I[K] : {
67
+ [P in `Error: Dynamic locator "${K}" expands to duplicate key(s): ${ExpandDynamicKey<K, I[K]> & (AllOtherExpandedTestIdKeys<I, K> | AllExpandedTestIdKeys<S>) & string}`]: never;
68
+ };
69
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export declare function getCallerLocation(): {
2
+ file: string;
3
+ line: number;
4
+ column: number;
5
+ } | undefined;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCallerLocation = getCallerLocation;
4
+ // Global stack trace filter to remove pw-core internal frames from all error stacks.
5
+ // This ensures that Playwright's auto-generated steps and expectations are attributed
6
+ // directly to the user's project files instead of showing internal pw-core library paths.
7
+ const originalPrepare = Error.prepareStackTrace;
8
+ Error.prepareStackTrace = (err, stack) => {
9
+ const filteredStack = stack.filter((frame) => {
10
+ const file = frame.getFileName();
11
+ if (!file)
12
+ return true;
13
+ const normalized = file.replace(/\\/g, '/');
14
+ if (normalized.includes('pw-core/src') ||
15
+ normalized.includes('pw-core/dist') ||
16
+ normalized.includes('node_modules/pw-core')) {
17
+ return false;
18
+ }
19
+ return true;
20
+ });
21
+ if (originalPrepare) {
22
+ try {
23
+ return originalPrepare(err, filteredStack);
24
+ }
25
+ catch {
26
+ // Fallback if originalPrepare fails on filtered stack
27
+ }
28
+ }
29
+ const errString = err.toString ? err.toString() : String(err);
30
+ return (errString +
31
+ '\n' +
32
+ filteredStack
33
+ .map((frame) => {
34
+ try {
35
+ return ' at ' + frame.toString();
36
+ }
37
+ catch {
38
+ return ' at <unknown>';
39
+ }
40
+ })
41
+ .join('\n'));
42
+ };
43
+ function getCallerLocation() {
44
+ const originalPrepareStackTrace = Error.prepareStackTrace;
45
+ try {
46
+ const err = {};
47
+ Error.prepareStackTrace = (_err, stack) => stack;
48
+ Error.captureStackTrace(err);
49
+ const stack = err.stack;
50
+ if (!stack)
51
+ return undefined;
52
+ for (let i = 1; i < stack.length; i++) {
53
+ const frame = stack[i];
54
+ const file = frame.getFileName();
55
+ if (!file)
56
+ continue;
57
+ const normalizedFile = file.replace(/\\/g, '/');
58
+ // Skip internal node_modules, node built-ins, and pw-core source/dist files
59
+ if (normalizedFile.includes('node_modules') ||
60
+ normalizedFile.includes('pw-core/src') ||
61
+ normalizedFile.includes('pw-core/dist') ||
62
+ normalizedFile.includes('playwright/lib') ||
63
+ normalizedFile.includes('@playwright') ||
64
+ normalizedFile.startsWith('node:') ||
65
+ !normalizedFile.includes('/')) {
66
+ continue;
67
+ }
68
+ const line = frame.getLineNumber();
69
+ const column = frame.getColumnNumber();
70
+ if (!line)
71
+ continue;
72
+ return { file, line, column: column ?? 1 };
73
+ }
74
+ return undefined;
75
+ }
76
+ catch {
77
+ return undefined;
78
+ }
79
+ finally {
80
+ Error.prepareStackTrace = originalPrepareStackTrace;
81
+ }
82
+ }
@@ -15,7 +15,14 @@ function formatStepDescription(methodName, target, args) {
15
15
  const targetStr = formatTarget(target);
16
16
  if (methodName === 'fill' && args[0] !== undefined) {
17
17
  const options = args[1];
18
- const shouldMask = !(options && typeof options === 'object' && options.mask === false);
18
+ let shouldMask = false;
19
+ if (options && typeof options === 'object' && options.mask !== undefined) {
20
+ shouldMask = options.mask === true;
21
+ }
22
+ else {
23
+ const targetStrLower = targetStr.toLowerCase();
24
+ shouldMask = targetStrLower.includes('pass') || targetStrLower.includes('pw');
25
+ }
19
26
  const displayValue = shouldMask ? '*'.repeat(String(args[0]).length) : args[0];
20
27
  return `Fill "${targetStr}" with "${displayValue}"`;
21
28
  }
@@ -30,7 +37,10 @@ function formatStepDescription(methodName, target, args) {
30
37
  if (methodName === 'uncheck')
31
38
  return `Uncheck "${targetStr}"`;
32
39
  const formattedMethod = methodName.charAt(0).toUpperCase() + methodName.slice(1);
33
- const cleanArgs = args.filter(a => typeof a === 'string' || typeof a === 'number').map(a => `"${a}"`).join(', ');
40
+ const cleanArgs = args
41
+ .filter((a) => typeof a === 'string' || typeof a === 'number')
42
+ .map((a) => `"${a}"`)
43
+ .join(', ');
34
44
  return `${formattedMethod} "${targetStr}"${cleanArgs ? ' with ' + cleanArgs : ''}`;
35
45
  }
36
46
  function formatAssertionDescription(target, matcherName, isNegated, args) {
@@ -42,8 +52,8 @@ function formatAssertionDescription(target, matcherName, isNegated, args) {
42
52
  toBeEnabled: isNegated ? 'is not enabled' : 'is enabled',
43
53
  toBeDisabled: isNegated ? 'is not disabled' : 'is disabled',
44
54
  toBeChecked: isNegated ? 'is not checked' : 'is checked',
45
- toHaveText: (isNegated ? 'does not have text "' : 'has text "') + args.map(a => String(a)).join(', ') + '"',
46
- toContainText: (isNegated ? 'does not contain "' : 'contains "') + args.map(a => String(a)).join(', ') + '"',
55
+ toHaveText: (isNegated ? 'does not have text "' : 'has text "') + args.map((a) => String(a)).join(', ') + '"',
56
+ toContainText: (isNegated ? 'does not contain "' : 'contains "') + args.map((a) => String(a)).join(', ') + '"',
47
57
  toHaveCount: (isNegated ? 'does not have count of "' : 'has count of "') + args[0] + '"'
48
58
  };
49
59
  return `${prefix} ${matcherMap[matcherName] || `${isNegated ? 'not ' : ''}${matcherName}`}`;
@@ -0,0 +1,4 @@
1
+ import { zeroArgMethodsList, oneArgMethodsList } from '../constants/methods';
2
+ export type AllowedZeroArgMethods = (typeof zeroArgMethodsList)[number];
3
+ export type AllowedOneArgMethods = (typeof oneArgMethodsList)[number];
4
+ export type AllowedMethodKeys = AllowedZeroArgMethods | AllowedOneArgMethods;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import { rolesList, strategyList } from '../constants/strategies';
2
+ export type RoleType = (typeof rolesList)[number];
3
+ export type StrategyType = (typeof strategyList)[number];
4
+ export type PlaywrightRoleOptions = {
5
+ exact?: boolean;
6
+ checked?: boolean;
7
+ disabled?: boolean;
8
+ expanded?: boolean;
9
+ includeHidden?: boolean;
10
+ level?: number;
11
+ pressed?: boolean;
12
+ selected?: boolean;
13
+ };
14
+ export type PlaywrightTextOptions = {
15
+ exact?: boolean;
16
+ };
17
+ export type LocatorStrategyOptions<S extends string> = S extends RoleType ? PlaywrightRoleOptions : S extends 'text' | 'label' | 'title' | 'placeholder' | 'altText' ? PlaywrightTextOptions : {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pw-core",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "workspaces": [
5
5
  "examples",
6
6
  "create-pw-core"
@@ -23,6 +23,9 @@
23
23
  "typescript"
24
24
  ],
25
25
  "main": "./dist/index.js",
26
+ "bin": {
27
+ "pw-core": "./dist/cli.js"
28
+ },
26
29
  "types": "./dist/index.d.ts",
27
30
  "files": [
28
31
  "dist",
@@ -58,10 +61,14 @@
58
61
  "devDependencies": {
59
62
  "@playwright/test": "^1.61.0",
60
63
  "@types/node": "^20.11.0",
64
+ "prettier": "^3.9.4",
61
65
  "rimraf": "^6.0.1",
62
66
  "typescript": "^5.3.3"
63
67
  },
64
68
  "publishConfig": {
65
69
  "access": "public"
70
+ },
71
+ "dependencies": {
72
+ "playwright-core": "^1.61.1"
66
73
  }
67
74
  }