@aarwitz/tapp 0.17.0-rc.6 → 0.17.0-rc.7
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/bin/tapp.js +11 -3
- package/mcp-server/src/html-report.js +21 -1
- package/package.json +1 -1
package/bin/tapp.js
CHANGED
|
@@ -1460,9 +1460,15 @@ switch (command) {
|
|
|
1460
1460
|
const runs = roots
|
|
1461
1461
|
.flatMap((root) => fs.readdirSync(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path.join(root, e.name)))
|
|
1462
1462
|
.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
|
|
1463
|
-
const
|
|
1463
|
+
const hasMarkers = (dir) => fs.existsSync(path.join(dir, "ocqa-markers.txt"));
|
|
1464
|
+
// `latest` (default) resolves to the newest *exploration* capture — the captures directory is
|
|
1465
|
+
// also full of flow-*/scenario-* evidence dirs with no ocqa-markers.txt, and picking the newest
|
|
1466
|
+
// of those made `tapp report` fail even though valid exploration captures existed. An explicitly
|
|
1467
|
+
// named capture is honored as-is so a non-exploration capture still gets a clear "no markers".
|
|
1468
|
+
const explicit = rest[0] && rest[0] !== "latest";
|
|
1469
|
+
const wanted = explicit ? runs.find((r) => path.basename(r) === rest[0]) : runs.find(hasMarkers);
|
|
1464
1470
|
if (!wanted) {
|
|
1465
|
-
bad("No captures found",
|
|
1471
|
+
bad("No captures found", explicit ? `no capture named "${rest[0]}"` : "run an exploration first (no capture with exploration markers was found)");
|
|
1466
1472
|
process.exit(1);
|
|
1467
1473
|
}
|
|
1468
1474
|
const { writeHtmlReport } = await import(path.join(packageRoot, "mcp-server", "src", "html-report.js"));
|
|
@@ -1472,7 +1478,9 @@ switch (command) {
|
|
|
1472
1478
|
process.exit(1);
|
|
1473
1479
|
}
|
|
1474
1480
|
ok("Evidence report", out);
|
|
1475
|
-
|
|
1481
|
+
// Only launch a browser from an interactive terminal — agents, scripts, and tests that invoke
|
|
1482
|
+
// `tapp report` non-interactively get the path without a surprise GUI window.
|
|
1483
|
+
if (process.stdout.isTTY) spawnSync("open", [out], { stdio: "ignore" });
|
|
1476
1484
|
break;
|
|
1477
1485
|
}
|
|
1478
1486
|
|
|
@@ -14,6 +14,22 @@ const SEV_COLOR = { critical: "#cf222e", high: "#bc4c00", medium: "#9a6700", low
|
|
|
14
14
|
|
|
15
15
|
const esc = (s) => String(s ?? "").replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ }[c]));
|
|
16
16
|
|
|
17
|
+
const VALID_PLATFORMS = new Set(["web", "android", "ios"]);
|
|
18
|
+
|
|
19
|
+
// Recover a capture's platform when no in-memory report is available. Prefer the run's persisted
|
|
20
|
+
// metadata (ui-map.json → app.platforms) — it is authoritative and survives a renamed folder — and
|
|
21
|
+
// fall back to the capture-id prefix (web-*/android-*, ios unprefixed) only for legacy captures that
|
|
22
|
+
// predate the map. Defaults to ios if nothing is resolvable, matching buildQaReport's own default.
|
|
23
|
+
export function capturePlatform(captureDir) {
|
|
24
|
+
try {
|
|
25
|
+
const map = JSON.parse(fs.readFileSync(path.join(captureDir, "ui-map.json"), "utf8"));
|
|
26
|
+
const fromMap = (map?.app?.platforms || []).find((p) => VALID_PLATFORMS.has(p));
|
|
27
|
+
if (fromMap) return fromMap;
|
|
28
|
+
} catch { /* no map, unreadable, or no valid platform — fall back to the id prefix */ }
|
|
29
|
+
const base = path.basename(captureDir);
|
|
30
|
+
return base.startsWith("web-") ? "web" : base.startsWith("android-") ? "android" : "ios";
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
// Two capture layouts exist: web runs write state_*.png at the capture root; iOS runs
|
|
18
34
|
// export XCUITest attachments into screenshots/ as UUID files with a manifest carrying
|
|
19
35
|
// the human-readable state_N_<Screen> names.
|
|
@@ -50,7 +66,11 @@ function collectShots(captureDir) {
|
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
export function writeHtmlReport(captureDir, { report, label = "", recordingWarning = "" } = {}) {
|
|
53
|
-
|
|
69
|
+
// Rebuild path (e.g. `tapp report`): no report object is passed, so buildQaReport would default to
|
|
70
|
+
// native — rendering a web/android page with the wrong "Checked / Not checked" scope, overclaiming
|
|
71
|
+
// native checks it never ran. Recover the run's real platform (metadata first, id prefix as a
|
|
72
|
+
// legacy fallback). When a report object IS passed (explore/init), it is already correct.
|
|
73
|
+
const r = report || buildQaReport(path.join(captureDir, "ocqa-markers.txt"), { platform: capturePlatform(captureDir) });
|
|
54
74
|
if (!r) return null;
|
|
55
75
|
|
|
56
76
|
const shots = collectShots(captureDir);
|
package/package.json
CHANGED