Skip to content

Commit 879a2cf

Browse files
aryanku-devclaude
andcommitted
Null-safe responsive config, defensive snapshot cast, DOM.disable cleanup
- responsive snapshot detection threw NPE when cliConfig.snapshot was missing or JSON-null; guard each layer before reading responsiveSnapshotCapture. - getSerializedDOM treated a null jse return as a Map and ClassCastException'd deep in the snapshot path. Detect non-Map results and raise a clear error pointing at the @percy/dom load failure as the root cause. - Pair every successful DOM.enable with DOM.disable in a finally block so the CDP session doesn't keep emitting DOM events after closed-shadow capture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f6e435a commit 879a2cf

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
},
66
"devDependencies": {
77
"@percy/cli": "1.31.10"
8-
}
8+
},
9+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
910
}

src/main/java/io/percy/selenium/Percy.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,11 @@ private boolean isCaptureResponsiveDOM(Map<String, Object> options) {
339339

340340
boolean responsiveSnapshotCaptureCLI = false;
341341
if (eligibleWidths == null) { return false; }
342-
if (cliConfig.getJSONObject("snapshot").has("responsiveSnapshotCapture")) {
343-
responsiveSnapshotCaptureCLI = cliConfig.getJSONObject("snapshot").getBoolean("responsiveSnapshotCapture");
342+
if (cliConfig != null && cliConfig.has("snapshot") && !cliConfig.isNull("snapshot")) {
343+
JSONObject snapshotCfg = cliConfig.getJSONObject("snapshot");
344+
if (snapshotCfg.has("responsiveSnapshotCapture") && !snapshotCfg.isNull("responsiveSnapshotCapture")) {
345+
responsiveSnapshotCaptureCLI = snapshotCfg.getBoolean("responsiveSnapshotCapture");
346+
}
344347
}
345348
Object responsiveSnapshotCaptureSDK = options.get("responsiveSnapshotCapture");
346349

@@ -973,7 +976,13 @@ private List<Map<String, Object>> processFrameTree(
973976
}
974977

975978
private Map<String, Object> getSerializedDOM(JavascriptExecutor jse, Set<Cookie> cookies, Map<String, Object> options) {
976-
Map<String, Object> domSnapshot = (Map<String, Object>) jse.executeScript(buildSnapshotJS(options));
979+
Object raw = jse.executeScript(buildSnapshotJS(options));
980+
if (!(raw instanceof Map)) {
981+
throw new RuntimeException("PercyDOM.serialize returned null or non-object; "
982+
+ "the @percy/dom script likely failed to load. Aborting snapshot.");
983+
}
984+
@SuppressWarnings("unchecked")
985+
Map<String, Object> domSnapshot = (Map<String, Object>) raw;
977986
Map<String, Object> mutableSnapshot = new HashMap<>(domSnapshot);
978987
mutableSnapshot.put("cookies", cookies);
979988

@@ -1061,8 +1070,10 @@ private void exposeClosedShadowRoots(WebDriver driver) {
10611070
if (!(driver instanceof ChromeDriver)) return;
10621071
ChromeDriver chrome;
10631072
try { chrome = (ChromeDriver) driver; } catch (ClassCastException e) { return; }
1073+
boolean domEnabled = false;
10641074
try {
10651075
chrome.executeCdpCommand("DOM.enable", new HashMap<>());
1076+
domEnabled = true;
10661077
Map<String, Object> getDocParams = new HashMap<>();
10671078
getDocParams.put("depth", -1);
10681079
getDocParams.put("pierce", true);
@@ -1111,6 +1122,14 @@ private void exposeClosedShadowRoots(WebDriver driver) {
11111122
}
11121123
} catch (Exception ex) {
11131124
log("Could not expose closed shadow roots via CDP: " + ex.getMessage(), "debug");
1125+
} finally {
1126+
// Release the DOM domain so subsequent commands don't keep emitting
1127+
// DOM events for this session. Best-effort — we don't care if this
1128+
// fails (e.g., session already closed).
1129+
if (domEnabled) {
1130+
try { chrome.executeCdpCommand("DOM.disable", new HashMap<>()); }
1131+
catch (Exception ignore) { /* defensive */ }
1132+
}
11141133
}
11151134
}
11161135

0 commit comments

Comments
 (0)