pw-core 1.3.0 → 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 +1 -0
  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
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Derives a camelCase registry key from element text with optional role suffix.
3
+ */
4
+ export declare function generateKeyFromText(text: string, role?: string): string;
5
+ /**
6
+ * Derives a camelCase key from a candidate's attribute or selector value.
7
+ * E.g. data-parent-id="why-pw-core" → whyPwCore
8
+ */
9
+ export declare function generateKeyFromCandidate(candidate: {
10
+ strategy: string;
11
+ selector: string;
12
+ valueToScore?: string;
13
+ }, role?: string): string;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateKeyFromText = generateKeyFromText;
4
+ exports.generateKeyFromCandidate = generateKeyFromCandidate;
5
+ const key_utils_1 = require("../key-utils");
6
+ /**
7
+ * Derives a camelCase registry key from element text with optional role suffix.
8
+ */
9
+ function generateKeyFromText(text, role) {
10
+ if (!text)
11
+ return '';
12
+ const roleSuffix = role === 'button' ? 'Btn' : undefined;
13
+ return (0, key_utils_1.toRegistryKey)(text, { roleSuffix });
14
+ }
15
+ /**
16
+ * Derives a camelCase key from a candidate's attribute or selector value.
17
+ * E.g. data-parent-id="why-pw-core" → whyPwCore
18
+ */
19
+ function generateKeyFromCandidate(candidate, role) {
20
+ const val = candidate.valueToScore || '';
21
+ if (!val)
22
+ return '';
23
+ // For data-attribute, id, testId strategies — use the attribute value directly
24
+ if (['dataAttribute', 'id', 'idAttribute', 'testId'].includes(candidate.strategy)) {
25
+ return generateKeyFromText(val, role);
26
+ }
27
+ // For role/label/text — use the text value
28
+ if (['role', 'label', 'text', 'placeholder', 'altText', 'title'].includes(candidate.strategy)) {
29
+ return generateKeyFromText(val, role);
30
+ }
31
+ return '';
32
+ }
@@ -1 +1,6 @@
1
+ declare global {
2
+ interface Window {
3
+ __pwCoreRecordHover?: (selector: string) => void;
4
+ }
5
+ }
1
6
  export declare function clientHoverTracker(): void;
@@ -6,6 +6,12 @@ function clientHoverTracker() {
6
6
  let hoverEntryTime = 0;
7
7
  let lastRecordedHover = null;
8
8
  let lastMutationTime = 0;
9
+ const recordHover = (element) => {
10
+ const selector = getUniqueCssSelector(element);
11
+ if (selector && window.__pwCoreRecordHover) {
12
+ window.__pwCoreRecordHover(selector);
13
+ }
14
+ };
9
15
  const getUniqueCssSelector = (el) => {
10
16
  if (el.getAttribute('data-testid')) {
11
17
  return `[data-testid="${el.getAttribute('data-testid')}"]`;
@@ -13,14 +19,15 @@ function clientHoverTracker() {
13
19
  if (el.getAttribute('data-parent-id')) {
14
20
  return `[data-parent-id="${el.getAttribute('data-parent-id')}"]`;
15
21
  }
16
- if (el.id) {
17
- return `#${el.id}`;
22
+ const htmlElement = el;
23
+ if (htmlElement.id) {
24
+ return `#${htmlElement.id}`;
18
25
  }
19
26
  if (el.tagName === 'BODY')
20
27
  return 'body';
21
28
  let path = el.tagName.toLowerCase();
22
- if (el.className) {
23
- const firstClass = el.className.split(/\s+/)[0];
29
+ if (typeof htmlElement.className === 'string' && htmlElement.className) {
30
+ const firstClass = htmlElement.className.split(/\s+/)[0];
24
31
  if (firstClass && !firstClass.includes('[') && !firstClass.includes(':')) {
25
32
  path += `.${firstClass}`;
26
33
  }
@@ -34,11 +41,7 @@ function clientHoverTracker() {
34
41
  const elapsed = Date.now() - hoverEntryTime;
35
42
  if (elapsed >= 150) {
36
43
  lastRecordedHover = lastHoveredElement;
37
- const selector = getUniqueCssSelector(lastHoveredElement);
38
- if (selector && window.__pwCoreRecordHover) {
39
- ;
40
- window.__pwCoreRecordHover(selector);
41
- }
44
+ recordHover(lastHoveredElement);
42
45
  }
43
46
  }
44
47
  });
@@ -49,7 +52,7 @@ function clientHoverTracker() {
49
52
  });
50
53
  document.addEventListener('mouseover', (e) => {
51
54
  const target = e.target;
52
- if (!target || target.closest('#pw-core-codegen-panel'))
55
+ if (!(target instanceof Element) || target.closest('#pw-core-codegen-panel'))
53
56
  return;
54
57
  const hoverTarget = target.closest('button, a, [role="menuitem"], [role="option"], .menu-item, [data-testid], svg, path, [data-parent-id]') || target;
55
58
  if (hoverTarget !== lastHoveredElement) {
@@ -62,11 +65,7 @@ function clientHoverTracker() {
62
65
  const sinceMutation = Date.now() - lastMutationTime;
63
66
  if (sinceMutation < 400) {
64
67
  lastRecordedHover = currentTarget;
65
- const selector = getUniqueCssSelector(currentTarget);
66
- if (selector && window.__pwCoreRecordHover) {
67
- ;
68
- window.__pwCoreRecordHover(selector);
69
- }
68
+ recordHover(currentTarget);
70
69
  }
71
70
  }
72
71
  }, 150);
@@ -17,12 +17,8 @@ class HoverTrackerManager {
17
17
  await this.context.exposeFunction('__pwCoreRecordHover', (selector) => {
18
18
  return this.options.onRecordHover(selector);
19
19
  });
20
- const fnStr = client_1.clientHoverTracker.toString();
21
- // 2. Add client script as init script
22
- await this.context.addInitScript((scriptStr) => {
23
- const fn = new Function(`return ${scriptStr}`)();
24
- fn();
25
- }, fnStr);
20
+ // 2. Add client script as init script directly via Playwright
21
+ await this.context.addInitScript(client_1.clientHoverTracker);
26
22
  }
27
23
  }
28
24
  exports.HoverTrackerManager = HoverTrackerManager;
@@ -1,35 +1,12 @@
1
- export interface SelectorMatch {
2
- type: string;
3
- val: string;
4
- }
5
- export interface MatchResult {
6
- pageKey: string;
7
- elementKey: string;
8
- val: string;
9
- type: string;
10
- isNew: boolean;
11
- }
12
- export declare function getSelectorValue(selector: string): SelectorMatch;
13
- export declare function findRegistryFile(dir: string): string | null;
14
- export declare function findPlaywrightConfig(dir: string): string | null;
15
- export declare function parseRegistry(filePath: string): any;
16
- export declare function matchDynamicEntry(val: string, entry: any, isTestId: boolean): {
17
- matches: boolean;
18
- matchedValue?: string;
19
- placeholderName?: string;
20
- };
21
- export declare function writeRegistry(filePath: string, registryObj: any, overrideMode?: boolean, usedPageKeys?: Set<string> | string[]): Record<string, string>;
22
- export declare function findPageKey(url: string, title: string, registryObj: any, overrideMode?: boolean): string;
23
- export declare function toCamelCase(str: string): string;
24
- export declare function findMatchInDict(val: string, strategyType: string, pageKey: string, registryObj: any, overrideMode?: boolean): MatchResult | null;
25
- export declare function findElementKey(selector: string, pageKey: string, registryObj: any, overrideMode?: boolean, extra?: {
26
- targetTestId?: string;
27
- targetId?: string;
28
- targetParentId?: string;
29
- overrideType?: string;
30
- }): MatchResult;
31
- export declare function formatActionCall(pageKey: string, elementKey: string, action: any, isTextSelector?: boolean, textValue?: string): string;
1
+ export * from './types';
2
+ export * from './key-utils';
3
+ export * from './uniqueness';
4
+ export * from './selector-parser';
5
+ export * from './project-finder';
6
+ export * from './registry-store';
7
+ export * from './registry-matcher';
8
+ export * from './action-formatter';
9
+ export * from './action-processor';
32
10
  export * from './config';
33
11
  export * from './generator/index';
34
- export * from './types';
35
12
  export * from './scorer';