cbrowser 7.4.12 → 7.4.14
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/dist/browser.d.ts +28 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +321 -0
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +45 -0
- package/dist/cli.js.map +1 -1
- package/dist/mcp-server-remote.d.ts.map +1 -1
- package/dist/mcp-server-remote.js +33 -5
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +31 -3
- package/dist/mcp-server.js.map +1 -1
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/visual/cross-browser.d.ts +3 -0
- package/dist/visual/cross-browser.d.ts.map +1 -1
- package/dist/visual/cross-browser.js +157 -43
- package/dist/visual/cross-browser.js.map +1 -1
- package/package.json +1 -1
package/dist/browser.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type Page } from "playwright";
|
|
7
7
|
import { type CBrowserConfig } from "./config.js";
|
|
8
|
-
import type { SavedSession, NavigationResult, ClickResult, ExtractResult, JourneyResult, CleanupOptions, CleanupResult, JourneyOptions, NetworkMock, NetworkRequest, PerformanceMetrics, PerformanceAuditResult, SmartRetryResult, AssertionResult, SelectorCacheEntry, SelectorCacheStats, PageAnalysis, TestGenerationResult } from "./types.js";
|
|
8
|
+
import type { SavedSession, NavigationResult, ClickResult, ExtractResult, JourneyResult, CleanupOptions, CleanupResult, JourneyOptions, NetworkMock, NetworkRequest, PerformanceMetrics, PerformanceAuditResult, SmartRetryResult, AssertionResult, SelectorCacheEntry, SelectorCacheStats, PageAnalysis, TestGenerationResult, DismissOverlayOptions, DismissOverlayResult } from "./types.js";
|
|
9
9
|
export declare class CBrowser {
|
|
10
10
|
private config;
|
|
11
11
|
private paths;
|
|
@@ -153,7 +153,34 @@ export declare class CBrowser {
|
|
|
153
153
|
force?: boolean;
|
|
154
154
|
maxRetries?: number;
|
|
155
155
|
retryDelay?: number;
|
|
156
|
+
dismissOverlays?: boolean;
|
|
156
157
|
}): Promise<SmartRetryResult>;
|
|
158
|
+
/** Common overlay patterns for detection */
|
|
159
|
+
private static readonly OVERLAY_PATTERNS;
|
|
160
|
+
/**
|
|
161
|
+
* Detect and dismiss overlays (cookie consent, age verification, newsletter popups).
|
|
162
|
+
* Constitutional safety: Yellow zone - logs all dismissed overlays.
|
|
163
|
+
*/
|
|
164
|
+
dismissOverlay(options?: DismissOverlayOptions): Promise<DismissOverlayResult>;
|
|
165
|
+
/** Text content keywords for overlay type classification */
|
|
166
|
+
private static readonly OVERLAY_TEXT_PATTERNS;
|
|
167
|
+
/**
|
|
168
|
+
* Classify an overlay by its text content.
|
|
169
|
+
*/
|
|
170
|
+
private classifyOverlayType;
|
|
171
|
+
/**
|
|
172
|
+
* Detect overlays on the page by analyzing position, z-index, pattern matching, and text content.
|
|
173
|
+
* Returns overlays sorted by z-index (highest first) so the topmost blocking overlay is dismissed first.
|
|
174
|
+
*/
|
|
175
|
+
private detectOverlays;
|
|
176
|
+
/**
|
|
177
|
+
* Try clicking a button, with force fallback if another element intercepts.
|
|
178
|
+
*/
|
|
179
|
+
private tryClickOverlayButton;
|
|
180
|
+
/**
|
|
181
|
+
* Attempt to dismiss a single detected overlay.
|
|
182
|
+
*/
|
|
183
|
+
private tryDismissOverlay;
|
|
157
184
|
/**
|
|
158
185
|
* Find alternative selectors for an element.
|
|
159
186
|
*/
|
package/dist/browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAA2C,KAAK,IAAI,EAAiD,MAAM,YAAY,CAAC;AAI/H,OAAO,EAAE,KAAK,cAAc,EAAgE,MAAM,aAAa,CAAC;AAEhH,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,aAAa,EAKb,cAAc,EACd,aAAa,EACb,cAAc,EAEd,WAAW,EACX,cAAc,EAId,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAEhB,eAAe,EAEf,kBAAkB,EAElB,kBAAkB,EAElB,YAAY,EAIZ,oBAAoB,
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/browser.js
CHANGED
|
@@ -876,6 +876,10 @@ class CBrowser {
|
|
|
876
876
|
const maxRetries = options.maxRetries ?? 3;
|
|
877
877
|
const retryDelay = options.retryDelay ?? 1000;
|
|
878
878
|
const attempts = [];
|
|
879
|
+
// Dismiss overlays first if requested
|
|
880
|
+
if (options.dismissOverlays) {
|
|
881
|
+
await this.dismissOverlay({ type: "auto", timeout: 3000 });
|
|
882
|
+
}
|
|
879
883
|
// First attempt with original selector
|
|
880
884
|
let result = await this.click(selector, { force: options.force });
|
|
881
885
|
attempts.push({
|
|
@@ -930,6 +934,323 @@ class CBrowser {
|
|
|
930
934
|
aiSuggestion,
|
|
931
935
|
};
|
|
932
936
|
}
|
|
937
|
+
// =========================================================================
|
|
938
|
+
// Overlay Detection & Dismissal (v7.4.14)
|
|
939
|
+
// =========================================================================
|
|
940
|
+
/** Common overlay patterns for detection */
|
|
941
|
+
static OVERLAY_PATTERNS = [
|
|
942
|
+
{
|
|
943
|
+
type: "cookie",
|
|
944
|
+
selectors: [
|
|
945
|
+
'[class*="cookie"]', '[id*="cookie"]', '[class*="consent"]', '[id*="consent"]',
|
|
946
|
+
'[class*="gdpr"]', '[id*="gdpr"]', '[class*="cc-"]', '[id*="cc-"]',
|
|
947
|
+
'[class*="CookieBanner"]', '[class*="cookie-banner"]', '[class*="cookie_banner"]',
|
|
948
|
+
'[aria-label*="cookie" i]', '[aria-label*="consent" i]',
|
|
949
|
+
],
|
|
950
|
+
closeButtons: [
|
|
951
|
+
'button:has-text("Accept")', 'button:has-text("Accept All")', 'button:has-text("Accept all")',
|
|
952
|
+
'button:has-text("I agree")', 'button:has-text("Agree")', 'button:has-text("Got it")',
|
|
953
|
+
'button:has-text("OK")', 'button:has-text("Allow")', 'button:has-text("Allow All")',
|
|
954
|
+
'button:has-text("Close")', '[class*="accept"]', '[class*="agree"]',
|
|
955
|
+
'[id*="accept"]', '[data-action="accept"]',
|
|
956
|
+
],
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
type: "age-verify",
|
|
960
|
+
selectors: [
|
|
961
|
+
'[class*="age-verif"]', '[id*="age-verif"]', '[class*="age_verif"]',
|
|
962
|
+
'[class*="age-gate"]', '[id*="age-gate"]', '[class*="agegate"]',
|
|
963
|
+
'[class*="age-check"]', '[id*="age-check"]',
|
|
964
|
+
'[role="dialog"]', '[aria-modal="true"]',
|
|
965
|
+
],
|
|
966
|
+
closeButtons: [
|
|
967
|
+
'button:has-text("I am 18")', 'button:has-text("I am 21")',
|
|
968
|
+
'button:has-text("I\'m 18")', 'button:has-text("I\'m 21")',
|
|
969
|
+
'button:has-text("I am over")', 'button:has-text("I\'m over")',
|
|
970
|
+
'button:has-text("Yes")', 'button:has-text("Enter")',
|
|
971
|
+
'button:has-text("Confirm")', 'button:has-text("Verify")',
|
|
972
|
+
'button:has-text("Enter Site")', 'button:has-text("Continue")',
|
|
973
|
+
],
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
type: "newsletter",
|
|
977
|
+
selectors: [
|
|
978
|
+
'[class*="newsletter"]', '[id*="newsletter"]',
|
|
979
|
+
'[class*="popup"]', '[id*="popup"]',
|
|
980
|
+
'[class*="subscribe"]', '[id*="subscribe"]',
|
|
981
|
+
'[class*="signup-modal"]', '[class*="email-capture"]',
|
|
982
|
+
],
|
|
983
|
+
closeButtons: [
|
|
984
|
+
'button:has-text("Close")', 'button:has-text("No thanks")',
|
|
985
|
+
'button:has-text("Not now")', 'button:has-text("Maybe later")',
|
|
986
|
+
'[class*="close"]', '[aria-label="Close"]', '[aria-label="close"]',
|
|
987
|
+
'button[class*="dismiss"]',
|
|
988
|
+
],
|
|
989
|
+
},
|
|
990
|
+
];
|
|
991
|
+
/**
|
|
992
|
+
* Detect and dismiss overlays (cookie consent, age verification, newsletter popups).
|
|
993
|
+
* Constitutional safety: Yellow zone - logs all dismissed overlays.
|
|
994
|
+
*/
|
|
995
|
+
async dismissOverlay(options = { type: "auto" }) {
|
|
996
|
+
const page = await this.getPage();
|
|
997
|
+
const timeout = options.timeout ?? 5000;
|
|
998
|
+
const details = [];
|
|
999
|
+
const maxPasses = 5; // Prevent infinite loops
|
|
1000
|
+
try {
|
|
1001
|
+
// Multi-pass dismissal: some sites reveal new overlays after dismissing the first
|
|
1002
|
+
for (let pass = 0; pass < maxPasses; pass++) {
|
|
1003
|
+
const detected = await this.detectOverlays(page, options);
|
|
1004
|
+
// Custom selector fallback on first pass if nothing detected
|
|
1005
|
+
if (pass === 0 && detected.length === 0 && options.customSelector) {
|
|
1006
|
+
try {
|
|
1007
|
+
const customEl = page.locator(options.customSelector).first();
|
|
1008
|
+
if (await customEl.isVisible({ timeout: 2000 })) {
|
|
1009
|
+
await customEl.click();
|
|
1010
|
+
await page.waitForTimeout(500);
|
|
1011
|
+
this.audit("dismiss-overlay", options.customSelector, "yellow", "success");
|
|
1012
|
+
details.push({
|
|
1013
|
+
type: "custom",
|
|
1014
|
+
selector: options.customSelector,
|
|
1015
|
+
dismissed: true,
|
|
1016
|
+
closeMethod: "custom-selector-click",
|
|
1017
|
+
});
|
|
1018
|
+
continue; // Re-detect after custom dismiss
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
catch { }
|
|
1022
|
+
}
|
|
1023
|
+
if (detected.length === 0)
|
|
1024
|
+
break; // No more overlays
|
|
1025
|
+
// Attempt to dismiss each detected overlay
|
|
1026
|
+
let dismissedThisPass = false;
|
|
1027
|
+
for (const overlay of detected) {
|
|
1028
|
+
const result = await this.tryDismissOverlay(page, overlay, timeout);
|
|
1029
|
+
details.push(result);
|
|
1030
|
+
if (result.dismissed) {
|
|
1031
|
+
this.audit("dismiss-overlay", result.selector, "yellow", "success");
|
|
1032
|
+
dismissedThisPass = true;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
if (!dismissedThisPass)
|
|
1036
|
+
break; // Can't dismiss anything, stop
|
|
1037
|
+
// Wait for any new overlays to appear
|
|
1038
|
+
await page.waitForTimeout(800);
|
|
1039
|
+
}
|
|
1040
|
+
const overlaysDismissed = details.filter(d => d.dismissed).length;
|
|
1041
|
+
const overlaysFound = details.length;
|
|
1042
|
+
return {
|
|
1043
|
+
dismissed: overlaysDismissed > 0,
|
|
1044
|
+
overlaysFound,
|
|
1045
|
+
overlaysDismissed,
|
|
1046
|
+
details,
|
|
1047
|
+
screenshot: await this.screenshot(),
|
|
1048
|
+
suggestion: overlaysDismissed === 0 && overlaysFound > 0
|
|
1049
|
+
? "Overlays detected but could not be dismissed automatically. Try providing a custom selector."
|
|
1050
|
+
: undefined,
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
catch (error) {
|
|
1054
|
+
return {
|
|
1055
|
+
dismissed: false,
|
|
1056
|
+
overlaysFound: 0,
|
|
1057
|
+
overlaysDismissed: 0,
|
|
1058
|
+
details,
|
|
1059
|
+
screenshot: await this.screenshot(),
|
|
1060
|
+
suggestion: `Error during overlay detection: ${error instanceof Error ? error.message : String(error)}`,
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
/** Text content keywords for overlay type classification */
|
|
1065
|
+
static OVERLAY_TEXT_PATTERNS = {
|
|
1066
|
+
"age-verify": ["age verif", "18+", "21+", "over 18", "over 21", "years or older", "age gate", "age check", "must be 18", "must be 21", "legal age", "adult content"],
|
|
1067
|
+
"cookie": ["cookie", "consent", "gdpr", "privacy policy", "we use cookies", "this site uses cookies", "accept cookies"],
|
|
1068
|
+
"newsletter": ["newsletter", "subscribe", "sign up for", "email updates", "stay updated", "join our mailing"],
|
|
1069
|
+
};
|
|
1070
|
+
/**
|
|
1071
|
+
* Classify an overlay by its text content.
|
|
1072
|
+
*/
|
|
1073
|
+
classifyOverlayType(text) {
|
|
1074
|
+
const lowerText = text.toLowerCase();
|
|
1075
|
+
for (const [type, keywords] of Object.entries(CBrowser.OVERLAY_TEXT_PATTERNS)) {
|
|
1076
|
+
if (keywords.some(kw => lowerText.includes(kw))) {
|
|
1077
|
+
return type;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return "unknown";
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Detect overlays on the page by analyzing position, z-index, pattern matching, and text content.
|
|
1084
|
+
* Returns overlays sorted by z-index (highest first) so the topmost blocking overlay is dismissed first.
|
|
1085
|
+
*/
|
|
1086
|
+
async detectOverlays(page, options) {
|
|
1087
|
+
const detected = [];
|
|
1088
|
+
try {
|
|
1089
|
+
// Unified detection: find all high-z-index fixed/absolute elements AND known pattern selectors
|
|
1090
|
+
const rawOverlays = await page.evaluate(() => {
|
|
1091
|
+
const results = [];
|
|
1092
|
+
const seen = new Set();
|
|
1093
|
+
const allElements = Array.from(document.querySelectorAll("*"));
|
|
1094
|
+
for (let i = 0; i < allElements.length; i++) {
|
|
1095
|
+
const el = allElements[i];
|
|
1096
|
+
if (seen.has(el))
|
|
1097
|
+
continue;
|
|
1098
|
+
const cs = window.getComputedStyle(el);
|
|
1099
|
+
const pos = cs.position;
|
|
1100
|
+
const zIndex = parseInt(cs.zIndex) || 0;
|
|
1101
|
+
const rect = el.getBoundingClientRect();
|
|
1102
|
+
const isDialog = el.getAttribute("role") === "dialog" || el.getAttribute("aria-modal") === "true";
|
|
1103
|
+
// Match: high z-index overlay OR dialog role
|
|
1104
|
+
if (((pos === "fixed" || pos === "absolute") && zIndex > 100 && rect.width > 200 && rect.height > 80) || isDialog) {
|
|
1105
|
+
if (rect.width < 50 || rect.height < 30)
|
|
1106
|
+
continue;
|
|
1107
|
+
if (cs.display === "none" || cs.visibility === "hidden" || cs.opacity === "0")
|
|
1108
|
+
continue;
|
|
1109
|
+
const text = (el.textContent || "").substring(0, 300).trim();
|
|
1110
|
+
let selector = el.tagName.toLowerCase();
|
|
1111
|
+
if (el.id)
|
|
1112
|
+
selector = `#${el.id}`;
|
|
1113
|
+
else if (el.className && typeof el.className === "string") {
|
|
1114
|
+
const cls = el.className.split(/\s+/).filter((c) => c.length > 0 && c.length < 40)[0];
|
|
1115
|
+
if (cls)
|
|
1116
|
+
selector = `.${cls}`;
|
|
1117
|
+
}
|
|
1118
|
+
seen.add(el);
|
|
1119
|
+
results.push({
|
|
1120
|
+
selector,
|
|
1121
|
+
text,
|
|
1122
|
+
zIndex: zIndex || (isDialog ? 99999 : 0),
|
|
1123
|
+
position: pos,
|
|
1124
|
+
role: el.getAttribute("role"),
|
|
1125
|
+
ariaModal: el.getAttribute("aria-modal"),
|
|
1126
|
+
width: Math.round(rect.width),
|
|
1127
|
+
height: Math.round(rect.height),
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return results;
|
|
1132
|
+
});
|
|
1133
|
+
// Classify and filter overlays
|
|
1134
|
+
for (const raw of rawOverlays) {
|
|
1135
|
+
const type = this.classifyOverlayType(raw.text);
|
|
1136
|
+
// Filter by requested type
|
|
1137
|
+
if (options.type && options.type !== "auto" && type !== options.type && type !== "unknown")
|
|
1138
|
+
continue;
|
|
1139
|
+
detected.push({
|
|
1140
|
+
type,
|
|
1141
|
+
selector: raw.selector,
|
|
1142
|
+
text: raw.text.substring(0, 200),
|
|
1143
|
+
zIndex: raw.zIndex,
|
|
1144
|
+
position: raw.position,
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
catch { }
|
|
1149
|
+
// Sort by z-index descending — dismiss topmost overlay first
|
|
1150
|
+
detected.sort((a, b) => b.zIndex - a.zIndex);
|
|
1151
|
+
// Deduplicate: keep only one per type (highest z-index)
|
|
1152
|
+
const seen = new Set();
|
|
1153
|
+
const deduped = [];
|
|
1154
|
+
for (const d of detected) {
|
|
1155
|
+
if (d.type !== "unknown" && seen.has(d.type))
|
|
1156
|
+
continue;
|
|
1157
|
+
seen.add(d.type);
|
|
1158
|
+
deduped.push(d);
|
|
1159
|
+
}
|
|
1160
|
+
return deduped;
|
|
1161
|
+
}
|
|
1162
|
+
/**
|
|
1163
|
+
* Try clicking a button, with force fallback if another element intercepts.
|
|
1164
|
+
*/
|
|
1165
|
+
async tryClickOverlayButton(btn, timeout) {
|
|
1166
|
+
try {
|
|
1167
|
+
await btn.click({ timeout: Math.min(timeout, 3000) });
|
|
1168
|
+
return true;
|
|
1169
|
+
}
|
|
1170
|
+
catch {
|
|
1171
|
+
// If normal click fails (e.g., another overlay intercepts), try force click
|
|
1172
|
+
try {
|
|
1173
|
+
await btn.click({ force: true, timeout: Math.min(timeout, 2000) });
|
|
1174
|
+
return true;
|
|
1175
|
+
}
|
|
1176
|
+
catch {
|
|
1177
|
+
return false;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Attempt to dismiss a single detected overlay.
|
|
1183
|
+
*/
|
|
1184
|
+
async tryDismissOverlay(page, overlay, timeout) {
|
|
1185
|
+
// Collect all close button selectors to try: matched pattern first, then all patterns, then generic
|
|
1186
|
+
const closeButtonSets = [];
|
|
1187
|
+
// First: close buttons from the matched overlay type pattern
|
|
1188
|
+
const matchedPattern = CBrowser.OVERLAY_PATTERNS.find(p => p.type === overlay.type);
|
|
1189
|
+
if (matchedPattern) {
|
|
1190
|
+
closeButtonSets.push({ source: "matched-pattern", selectors: matchedPattern.closeButtons });
|
|
1191
|
+
}
|
|
1192
|
+
// Second: close buttons from all other patterns (in case classification was imperfect)
|
|
1193
|
+
for (const pattern of CBrowser.OVERLAY_PATTERNS) {
|
|
1194
|
+
if (pattern.type !== overlay.type) {
|
|
1195
|
+
closeButtonSets.push({ source: `${pattern.type}-pattern`, selectors: pattern.closeButtons });
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
// Third: generic close buttons
|
|
1199
|
+
closeButtonSets.push({
|
|
1200
|
+
source: "generic",
|
|
1201
|
+
selectors: [
|
|
1202
|
+
'button[aria-label="Close"]', 'button[aria-label="close"]',
|
|
1203
|
+
'button[aria-label="Dismiss"]', '[role="button"][aria-label="Close"]',
|
|
1204
|
+
'button[class*="close"]', '[class*="close-btn"]', '[class*="closeBtn"]',
|
|
1205
|
+
'button:has-text("×")', 'button:has-text("✕")', 'button:has-text("X")',
|
|
1206
|
+
'button:has-text("Close")', 'button:has-text("Dismiss")',
|
|
1207
|
+
'button:has-text("No thanks")', 'button:has-text("Not now")',
|
|
1208
|
+
],
|
|
1209
|
+
});
|
|
1210
|
+
// Try all close button sets
|
|
1211
|
+
for (const set of closeButtonSets) {
|
|
1212
|
+
for (const btnSelector of set.selectors) {
|
|
1213
|
+
try {
|
|
1214
|
+
const btn = page.locator(btnSelector).first();
|
|
1215
|
+
if (await btn.isVisible({ timeout: 800 })) {
|
|
1216
|
+
const clicked = await this.tryClickOverlayButton(btn, timeout);
|
|
1217
|
+
if (clicked) {
|
|
1218
|
+
await page.waitForTimeout(500);
|
|
1219
|
+
return {
|
|
1220
|
+
type: overlay.type,
|
|
1221
|
+
selector: overlay.selector,
|
|
1222
|
+
dismissed: true,
|
|
1223
|
+
closeMethod: `${set.source}: ${btnSelector}`,
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
catch { }
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
// Last resort: Try pressing Escape
|
|
1232
|
+
try {
|
|
1233
|
+
await page.keyboard.press("Escape");
|
|
1234
|
+
await page.waitForTimeout(500);
|
|
1235
|
+
// Check if overlay is still visible
|
|
1236
|
+
const stillVisible = await page.$(overlay.selector);
|
|
1237
|
+
if (!stillVisible || !(await stillVisible.isVisible())) {
|
|
1238
|
+
return {
|
|
1239
|
+
type: overlay.type,
|
|
1240
|
+
selector: overlay.selector,
|
|
1241
|
+
dismissed: true,
|
|
1242
|
+
closeMethod: "escape-key",
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
catch { }
|
|
1247
|
+
return {
|
|
1248
|
+
type: overlay.type,
|
|
1249
|
+
selector: overlay.selector,
|
|
1250
|
+
dismissed: false,
|
|
1251
|
+
error: "Could not find a way to dismiss this overlay",
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
933
1254
|
/**
|
|
934
1255
|
* Find alternative selectors for an element.
|
|
935
1256
|
*/
|