#!/usr/bin/env bash # End-to-end check of the web build: serve it, load it in headless Chrome, # and confirm Nim actually produced a fractal in the browser. # # "It compiled" is not the bar here. dart:js_interop failures and wasm load # failures both look like a clean build and a blank canvas, so this asserts on # the rendered pixels and on the absence of uncaught exceptions. set -euo pipefail cd "$(dirname "$0")/.." chrome="${CHROME_EXECUTABLE:-$(command -v google-chrome-stable || command -v google-chrome || command -v chromium || true)}" [ -n "$chrome" ] || { echo "no Chrome found; set CHROME_EXECUTABLE"; exit 1; } [ -d example/build/web ] || { echo "run 'just build-web' first"; exit 1; } [ -f example/build/web/nimflutter.wasm ] || { echo "example/build/web/nimflutter.wasm missing"; exit 1; } work="$(mktemp -d)" port="${PORT:-8791}" python3 -m http.server "$port" --bind 127.0.0.1 --directory example/build/web >/dev/null 2>&1 & server=$! trap 'kill $server 2>/dev/null || true; rm -rf "$work"' EXIT sleep 2 "$chrome" --headless=new --no-sandbox --disable-dev-shm-usage \ --enable-unsafe-swiftshader --virtual-time-budget=30000 \ --window-size=1280,900 --screenshot="$work/shot.png" \ --enable-logging=stderr --v=1 \ "http://127.0.0.1:$port/index.html" >/dev/null 2>"$work/chrome.log" # Uncaught Dart/JS exceptions surface as CONSOLE lines. if grep -qE 'CONSOLE.*(Uncaught|Unhandled)' "$work/chrome.log"; then echo "FAIL uncaught exception in the browser:" grep -oE 'CONSOLE:[0-9]+\] "[^"]*' "$work/chrome.log" | head -5 exit 1 fi python3 - "$work/shot.png" <<'EOF' import sys from PIL import Image im = Image.open(sys.argv[1]).convert('RGB') w, h = im.size # The canvas is the left ~70%; the right is the control panel. canvas = im.crop((0, 0, int(w * 0.7), h)) colors = canvas.getcolors(maxcolors=1 << 24) or [] distinct = len(colors) black = sum(n for n, c in colors if c == (0, 0, 0)) total = canvas.size[0] * canvas.size[1] print(f"canvas {canvas.size[0]}x{canvas.size[1]}: {distinct} distinct colours, " f"{100 * black / total:.1f}% pure black") # A blank/failed canvas is one flat colour. A real frame has the black # interior of the set plus a smooth coloured exterior. if distinct < 200: sys.exit(f"FAIL canvas has only {distinct} distinct colours — nothing rendered") if not (0.05 < black / total < 0.75): sys.exit(f"FAIL black fraction {black / total:.2f} does not look like the set") print("ok Nim rendered a Mandelbrot frame in the browser") EOF