fix(ci): read the suite file of Flutter widget tests in flake check

The Flutter flake-check lane marked every iteration FAILED on PR #8601
even though `flutter test` passed all 65 selected tests. The Dart JSON
reporter gives a test declared through a helper, which includes every
`testWidgets`, the helper's `package:flutter_test/...` url and puts the
suite file in `root_url`. parseDartReport passed that `package:` url to
fileURLToPath, which throws ERR_INVALID_URL_SCHEME. repeatDart's catch
then turned the throw into an empty status map, so any selection that
contained a widget test could never pass.

parseDartReport now prefers `root_url` and falls back to `url`. Parsing
the CI run's iter-1.json report now gives 65 passed and 1 skipped, which
matches flutter's own summary. The parser table gains a widget-test
event, and that row fails with ERR_INVALID_URL_SCHEME without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
Matt Toohey
2026-10-29 21:02:36 +11:00
parent a6294cc62e
commit bd87d8e877
2 changed files with 23 additions and 1 deletions

View File

@@ -1115,6 +1115,8 @@ function repeatNode(files, iterations) {
// Per-test statuses of a `dart test` JSON report (one event per line), keyed
// `<file> › <name>`. Hidden entries are the runner's own file-loading steps.
// A test declared through a helper (every `testWidgets`) has the helper's
// `package:` url; `root_url` then names the suite file.
export function parseDartReport(text, mobileRoot = `${root}mobile/`) {
const started = new Map();
const statuses = new Map();
@@ -1129,7 +1131,10 @@ export function parseDartReport(text, mobileRoot = `${root}mobile/`) {
if (event.type !== "testDone" || event.hidden) continue;
const test = started.get(event.testID);
if (!test) continue;
const file = fileURLToPath(test.url ?? "file:///").replace(mobileRoot, "");
const file = fileURLToPath(test.root_url ?? test.url ?? "file:///").replace(
mobileRoot,
"",
);
statuses.set(
`${file} › ${test.name}`,
event.skipped

View File

@@ -951,6 +951,15 @@ test("reports give per-test statuses per iteration", () => {
type: "testStart",
test: { id: 4, name: "later", url: "file:///m/test/b_test.dart" },
}),
event({
type: "testStart",
test: {
id: 5,
name: "widget",
url: "package:flutter_test/src/widget_tester.dart",
root_url: "file:///m/test/b_test.dart",
},
}),
"not json",
event({
type: "testDone",
@@ -973,6 +982,13 @@ test("reports give per-test statuses per iteration", () => {
hidden: false,
skipped: true,
}),
event({
type: "testDone",
testID: 5,
result: "success",
hidden: false,
skipped: false,
}),
event({ type: "done", success: false }),
].join("\n"),
"/m/",
@@ -981,6 +997,7 @@ test("reports give per-test statuses per iteration", () => {
["test/a_test.dart › group renders", "passed"],
["test/a_test.dart › group fails", "failed"],
["test/b_test.dart › later", "skipped"],
["test/b_test.dart › widget", "passed"],
]),
);
// Playwright lists a --repeat-each journey once per repetition, in order.