Print browser console/errors in non-JSON mode
This commit is contained in:
parent
9db730718b
commit
37be8efeb0
2 changed files with 117 additions and 2 deletions
|
|
@ -2028,6 +2028,33 @@ struct CMUXCLI {
|
|||
return String(describing: value)
|
||||
}
|
||||
|
||||
func displayBrowserLogItems(_ value: Any?) -> String? {
|
||||
guard let items = value as? [Any], !items.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let lines = items.map { item -> String in
|
||||
guard let dict = item as? [String: Any] else {
|
||||
return displayBrowserValue(item)
|
||||
}
|
||||
|
||||
let text = (dict["text"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
let levelRaw = (dict["level"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
let level = levelRaw.isEmpty ? "log" : levelRaw
|
||||
|
||||
if text.isEmpty {
|
||||
if let message = (dict["message"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!message.isEmpty {
|
||||
return "[error] \(message)"
|
||||
}
|
||||
return displayBrowserValue(dict)
|
||||
}
|
||||
return "[\(level)] \(text)"
|
||||
}
|
||||
|
||||
return lines.joined(separator: "\n")
|
||||
}
|
||||
|
||||
func nonFlagArgs(_ values: [String]) -> [String] {
|
||||
values.filter { !$0.hasPrefix("-") }
|
||||
}
|
||||
|
|
@ -2812,7 +2839,8 @@ struct CMUXCLI {
|
|||
throw CLIError(message: "Unsupported browser console subcommand: \(consoleVerb)")
|
||||
}
|
||||
let payload = try client.sendV2(method: method, params: ["surface_id": sid])
|
||||
output(payload, fallback: "OK")
|
||||
let fallback = displayBrowserLogItems(payload["entries"]) ?? "OK"
|
||||
output(payload, fallback: fallback)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -2826,7 +2854,8 @@ struct CMUXCLI {
|
|||
throw CLIError(message: "Unsupported browser errors subcommand: \(errorsVerb)")
|
||||
}
|
||||
let payload = try client.sendV2(method: "browser.errors.list", params: params)
|
||||
output(payload, fallback: "OK")
|
||||
let fallback = displayBrowserLogItems(payload["errors"]) ?? "OK"
|
||||
output(payload, fallback: fallback)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
86
tests/test_browser_console_errors_cli_output_regression.py
Normal file
86
tests/test_browser_console_errors_cli_output_regression.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Static regression guard for browser console/errors CLI output formatting.
|
||||
|
||||
Ensures non-JSON `browser console list` and `browser errors list` do not fall
|
||||
back to unconditional `OK` when logs exist.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def repo_root() -> Path:
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return Path(result.stdout.strip())
|
||||
return Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def extract_block(source: str, signature: str) -> str:
|
||||
start = source.find(signature)
|
||||
if start < 0:
|
||||
raise ValueError(f"Missing signature: {signature}")
|
||||
brace_start = source.find("{", start)
|
||||
if brace_start < 0:
|
||||
raise ValueError(f"Missing opening brace for: {signature}")
|
||||
depth = 0
|
||||
for idx in range(brace_start, len(source)):
|
||||
char = source[idx]
|
||||
if char == "{":
|
||||
depth += 1
|
||||
elif char == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return source[brace_start : idx + 1]
|
||||
raise ValueError(f"Unbalanced braces for: {signature}")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
root = repo_root()
|
||||
failures: list[str] = []
|
||||
|
||||
cli_path = root / "CLI" / "cmux.swift"
|
||||
cli_source = cli_path.read_text(encoding="utf-8")
|
||||
browser_block = extract_block(cli_source, "private func runBrowserCommand(")
|
||||
|
||||
if "func displayBrowserLogItems(_ value: Any?) -> String?" not in browser_block:
|
||||
failures.append("runBrowserCommand() is missing displayBrowserLogItems() helper")
|
||||
else:
|
||||
helper_block = extract_block(browser_block, "func displayBrowserLogItems(_ value: Any?) -> String?")
|
||||
if "return \"[\\(level)] \\(text)\"" not in helper_block:
|
||||
failures.append("displayBrowserLogItems() no longer renders level-prefixed log lines")
|
||||
if "return \"[error] \\(message)\"" not in helper_block:
|
||||
failures.append("displayBrowserLogItems() no longer renders concise JS error messages")
|
||||
if "return displayBrowserValue(dict)" not in helper_block:
|
||||
failures.append("displayBrowserLogItems() no longer falls back to structured formatting")
|
||||
|
||||
console_block = extract_block(browser_block, 'if subcommand == "console"')
|
||||
if 'displayBrowserLogItems(payload["entries"])' not in console_block:
|
||||
failures.append("browser console path no longer formats entries for non-JSON output")
|
||||
if 'output(payload, fallback: "OK")' in console_block:
|
||||
failures.append("browser console path regressed to unconditional OK output")
|
||||
|
||||
errors_block = extract_block(browser_block, 'if subcommand == "errors"')
|
||||
if 'displayBrowserLogItems(payload["errors"])' not in errors_block:
|
||||
failures.append("browser errors path no longer formats errors for non-JSON output")
|
||||
if 'output(payload, fallback: "OK")' in errors_block:
|
||||
failures.append("browser errors path regressed to unconditional OK output")
|
||||
|
||||
if failures:
|
||||
print("FAIL: browser console/errors CLI output regression guard failed")
|
||||
for item in failures:
|
||||
print(f" - {item}")
|
||||
return 1
|
||||
|
||||
print("PASS: browser console/errors CLI output regression guard is in place")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue