test(browser): drive console.error through to a fired property

Claude-Session: https://claude.ai/code/session_01ShuAy8q8ZfPi8KHxwc8JpQ
This commit is contained in:
pj committed 2026-08-16 01:42:50 +05:30
1 parent 3bab5c3f5c
commit a6b3ccee58
3 files changed
+65

No files matched your search

+27
View File
@@ -81,6 +81,33 @@ func TestBrowserConsoleErrorReachesTheSpec(t *testing.T) {
} }
} }
// TestBrowserConsoleErrorFiresTheLogProperty drives the same page through the
// whole bundle -> run -> verify pipeline instead of hand-assembling a snapshot.
// The driver holding the entry is not enough on web: every extractor reading is
// replaced by the one the page computed, so state.logs is whatever the page
// says it is, and a page that answers "no logs" leaves noLogcatErrors green on
// a run whose console was full of errors.
func TestBrowserConsoleErrorFiresTheLogProperty(t *testing.T) {
violations := runFixture(t, "console-levels")
if !slices.Contains(violations, "noLogcatErrors") {
t.Fatalf("a page calling console.error ran a whole run without noLogcatErrors firing; violations=%v", violations)
}
}
// TestBrowserQuietPageKeepsTheLogPropertySatisfied is the other half: a page
// whose console never reaches the error level must leave noLogcatErrors alone,
// so the property is reporting what the page logged rather than being on
// whenever the run is web.
func TestBrowserQuietPageKeepsTheLogPropertySatisfied(t *testing.T) {
violations := runFixture(t, "console-quiet")
if slices.Contains(violations, "noLogcatErrors") {
t.Errorf("noLogcatErrors fired on a page that logged nothing at error level; violations=%v", violations)
}
if !slices.Contains(violations, "counterNeverMoves") {
t.Fatalf("nothing was ever pressed, so the run proves nothing about a property that can fire; violations=%v", violations)
}
}
// TestBrowserConsoleLevelsMapToTheLogcatScale pins what each console verb // TestBrowserConsoleLevelsMapToTheLogcatScale pins what each console verb
// becomes once it crosses the driver. driver.LogEntry.Level is the single-letter // becomes once it crosses the driver. driver.LogEntry.Level is the single-letter
// logcat scale on every platform, so a spec asking for warnings or debug lines // logcat scale on every platform, so a spec asking for warnings or debug lines
+23
View File
@@ -0,0 +1,23 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>console-quiet</title>
</head>
<body>
<button id="press" style="width:200px;height:80px">press</button>
<div id="count">0</div>
<script>
// Noisy below the error level. A run that reports these as errors is
// reporting a healthy page as broken.
console.warn("a warning");
console.log("a plain log");
console.info("an info line");
let presses = 0;
document.getElementById("press").addEventListener("click", function () {
presses += 1;
document.getElementById("count").textContent = String(presses);
});
</script>
</body>
</html>
+15
View File
@@ -0,0 +1,15 @@
import { always, extract, taps } from "@sanderling/spec";
import { noLogcatErrors } from "@sanderling/spec/defaults/properties";
const presses = extract((s) => {
const el = s.ax.find({ id: "count" });
return el ? parseInt(el.text, 10) || 0 : 0;
}).named("presses");
// The run has to actually be driving the page, or noLogcatErrors staying
// satisfied says nothing about whether it can fire at all.
const counterNeverMoves = always(() => presses.current === 0);
export const properties = { noLogcatErrors, counterNeverMoves };
export const actionsRoot = taps;