@empiricalrun/playwright-utils 0.19.32 → 0.19.33

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @empiricalrun/playwright-utils
2
2
 
3
+ ## 0.19.33
4
+
5
+ ### Patch Changes
6
+
7
+ - 7b19602: feat: use overlay text content to improve overlay dismissal accuracy
8
+ - b6d1326: fix: z-index scaling for better overlay dismissals
9
+ - Updated dependencies [7b19602]
10
+ - Updated dependencies [b6d1326]
11
+ - Updated dependencies [f462463]
12
+ - @empiricalrun/test-gen@0.42.21
13
+
3
14
  ## 0.19.32
4
15
 
5
16
  ### Patch Changes
@@ -1,9 +1,11 @@
1
1
  import type { Locator } from "@playwright/test";
2
- export declare function extractInterceptingElement(errorMessage: string): {
2
+ type OverlayElement = {
3
3
  interceptor: string;
4
4
  parent: string | undefined;
5
- } | undefined;
5
+ };
6
+ export declare function extractInterceptingElement(errorMessage: string): OverlayElement | undefined;
6
7
  export declare function patchClick(LocatorClass: Function & {
7
8
  prototype: Locator;
8
9
  }): void;
10
+ export {};
9
11
  //# sourceMappingURL=click.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/highlight/click.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAQ,MAAM,kBAAkB,CAAC;AA6BtD,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAC3D;IACE,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,GACD,SAAS,CAiCZ;AAmDD,wBAAgB,UAAU,CAAC,YAAY,EAAE,QAAQ,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,QAwCzE"}
1
+ {"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../../../../src/test/scripts/pw-locator-patch/highlight/click.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAQ,MAAM,kBAAkB,CAAC;AA6BtD,KAAK,cAAc,GAAG;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,GACnB,cAAc,GAAG,SAAS,CAiC5B;AAwGD,wBAAgB,UAAU,CAAC,YAAY,EAAE,QAAQ,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,QA2CzE"}
@@ -63,27 +63,71 @@ function extractInterceptingElement(errorMessage) {
63
63
  }
64
64
  }
65
65
  exports.extractInterceptingElement = extractInterceptingElement;
66
- function overlayElementInfo(errorMessage) {
67
- try {
68
- const elements = extractInterceptingElement(errorMessage);
69
- if (elements) {
70
- const { interceptor, parent } = elements;
71
- if (parent) {
72
- return `${interceptor} inside ${parent}`;
73
- }
74
- else {
75
- return `${interceptor}`;
76
- }
66
+ function description(element) {
67
+ if (element) {
68
+ const { interceptor, parent } = element;
69
+ if (parent) {
70
+ return `${interceptor} inside ${parent}`;
71
+ }
72
+ else {
73
+ return `${interceptor}`;
77
74
  }
78
75
  }
79
- catch (e) {
80
- // Ignoring errors on this for now, since we're only using element
81
- // info for logging.
76
+ }
77
+ async function textContent(pageRef, element) {
78
+ if (element) {
79
+ const { interceptor, parent } = element;
80
+ let startTag = parent ? parent : interceptor;
81
+ let endTag;
82
+ const match = startTag.match(/^<\s*([^\s>]+)/);
83
+ if (match) {
84
+ const tagName = match[1]; // "div"
85
+ endTag = `</${tagName}>`;
86
+ }
87
+ if (!startTag || !endTag) {
88
+ return undefined;
89
+ }
90
+ return await pageRef.evaluate((tags) => {
91
+ const [startTag, endTag] = tags;
92
+ const htmlString = `${startTag}temp${endTag}`;
93
+ const parser = new DOMParser();
94
+ const doc = parser.parseFromString(htmlString, "text/html");
95
+ const tempEl = doc.body.firstElementChild;
96
+ let selector = tempEl.tagName.toLowerCase(); // start with the tag name, e.g., 'div'
97
+ // If there's an id, add it (id is unique and very specific)
98
+ if (tempEl.id) {
99
+ selector += `#${tempEl.id}`;
100
+ }
101
+ // Add all classes (if any)
102
+ if (tempEl.classList.length > 0) {
103
+ tempEl.classList.forEach((cls) => {
104
+ selector += `.${cls}`;
105
+ });
106
+ }
107
+ // Add any other attributes that might help narrow it down.
108
+ // (Skip 'id' and 'class' because they are already included.)
109
+ Array.from(tempEl.attributes).forEach((attr) => {
110
+ if (attr.name === "id" || attr.name === "class")
111
+ return;
112
+ // Note: if attribute values contain special characters, consider escaping them.
113
+ selector += `[${attr.name}="${attr.value}"]`;
114
+ });
115
+ const realElement = document.querySelector(selector);
116
+ return realElement?.textContent?.trim();
117
+ }, [startTag, endTag]);
82
118
  }
83
119
  }
84
- async function runAgentOnOverlay(pageRef) {
120
+ async function runAgentOnOverlay(pageRef, element) {
121
+ const content = await textContent(pageRef, element);
122
+ const promptAddition = content
123
+ ? `
124
+ The popup can be identified with its text content:
125
+ ${content}`
126
+ : ``;
85
127
  const plannerResp = await (0, planner_1.runtimePlannerWithScreenshot)({
86
- task: "Find a way to dismiss the popup. If the popup is non dismissible or there is no popup then return immediately. Also note that you just need to dismiss popup and do nothing else.",
128
+ task: `
129
+ Find a way to dismiss the popup. If the popup is non dismissible or there is no popup then return immediately.
130
+ Also note that you just need to dismiss popup and do nothing else.`,
87
131
  conversation: [],
88
132
  page: pageRef,
89
133
  });
@@ -91,7 +135,12 @@ async function runAgentOnOverlay(pageRef) {
91
135
  throw new Error("No active popup found");
92
136
  }
93
137
  await (0, run_1.createTestUsingMasterAgent)({
94
- task: "Find a way to dismiss the popup. If the popup is non dismissible or there is no popup then return immediately. Also note that you just need to dismiss popup and do nothing else.",
138
+ task: `
139
+ Find a way to dismiss the popup. If the popup is non dismissible or there is no popup then return immediately.
140
+ Also note that you just need to dismiss popup and do nothing else.
141
+
142
+ ${promptAddition}
143
+ `,
95
144
  page: pageRef,
96
145
  options: {
97
146
  useActionSpecificAnnotations: true,
@@ -106,10 +155,6 @@ function annotateForReport(description) {
106
155
  description,
107
156
  });
108
157
  }
109
- function isSurvicateOverlay(errorMessage) {
110
- const element = overlayElementInfo(errorMessage);
111
- return element?.includes("survicate");
112
- }
113
158
  function patchClick(LocatorClass) {
114
159
  // Check if already patched
115
160
  if (isClickPatched.get(LocatorClass)) {
@@ -129,15 +174,16 @@ function patchClick(LocatorClass) {
129
174
  if (!originalError.message?.includes(ERROR_SUBSTRING_INTERCEPTION)) {
130
175
  throw originalError;
131
176
  }
132
- annotateForReport(`Attempting to auto-dismiss overlay ${overlayElementInfo(originalError.message)}`);
177
+ let overlayElement = undefined;
178
+ try {
179
+ overlayElement = extractInterceptingElement(originalError.message);
180
+ }
181
+ catch (err) {
182
+ // Ignoring this error
183
+ }
184
+ annotateForReport(`Attempting to auto-dismiss overlay: ${description(overlayElement)}`);
133
185
  try {
134
- if (isSurvicateOverlay(originalError.message)) {
135
- // TODO: Survicate specific handling that bypasses the agent; this is temporary!
136
- await this._frame._page.getByLabel("Close the survey").click();
137
- }
138
- else {
139
- await runAgentOnOverlay(this._frame._page);
140
- }
186
+ await runAgentOnOverlay(this._frame._page, overlayElement);
141
187
  }
142
188
  catch (agentError) {
143
189
  annotateForReport(`Error in overlay dismiss: ${agentError.toString()}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/playwright-utils",
3
- "version": "0.19.32",
3
+ "version": "0.19.33",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -44,7 +44,7 @@
44
44
  "rimraf": "^6.0.1",
45
45
  "@empiricalrun/llm": "^0.9.32",
46
46
  "@empiricalrun/r2-uploader": "^0.3.8",
47
- "@empiricalrun/test-gen": "^0.42.20"
47
+ "@empiricalrun/test-gen": "^0.42.21"
48
48
  },
49
49
  "scripts": {
50
50
  "dev": "tsc --build --watch",