| Add a WebAssembly backend for the example 728acaa nandithebull 19h ago | 1 | #!/usr/bin/env bash |
| 2 | # End-to-end check of the web build: serve it, load it in headless Chrome, |
| Replace V with Nim 472eb49 nandithebull 19h ago | 3 | # and confirm Nim actually produced a fractal in the browser. |
| Add a WebAssembly backend for the example 728acaa nandithebull 19h ago | 4 | # |
| 5 | # "It compiled" is not the bar here. dart:js_interop failures and wasm load |
| 6 | # failures both look like a clean build and a blank canvas, so this asserts on |
| 7 | # the rendered pixels and on the absence of uncaught exceptions. |
| 8 | set -euo pipefail |
| 9 | cd "$(dirname "$0")/.." |
| 10 | |
| 11 | chrome="${CHROME_EXECUTABLE:-$(command -v google-chrome-stable || command -v google-chrome || command -v chromium || true)}" |
| 12 | [ -n "$chrome" ] || { echo "no Chrome found; set CHROME_EXECUTABLE"; exit 1; } |
| 13 | [ -d example/build/web ] || { echo "run 'just build-web' first"; exit 1; } |
| Replace V with Nim 472eb49 nandithebull 19h ago | 14 | [ -f example/build/web/nimflutter.wasm ] || { echo "example/build/web/nimflutter.wasm missing"; exit 1; } |
| Add a WebAssembly backend for the example 728acaa nandithebull 19h ago | 15 | |
| 16 | work="$(mktemp -d)" |
| 17 | port="${PORT:-8791}" |
| 18 | python3 -m http.server "$port" --bind 127.0.0.1 --directory example/build/web >/dev/null 2>&1 & |
| 19 | server=$! |
| 20 | trap 'kill $server 2>/dev/null || true; rm -rf "$work"' EXIT |
| 21 | sleep 2 |
| 22 | |
| 23 | "$chrome" --headless=new --no-sandbox --disable-dev-shm-usage \ |
| 24 | --enable-unsafe-swiftshader --virtual-time-budget=30000 \ |
| 25 | --window-size=1280,900 --screenshot="$work/shot.png" \ |
| 26 | --enable-logging=stderr --v=1 \ |
| 27 | "http://127.0.0.1:$port/index.html" >/dev/null 2>"$work/chrome.log" |
| 28 | |
| 29 | # Uncaught Dart/JS exceptions surface as CONSOLE lines. |
| 30 | if grep -qE 'CONSOLE.*(Uncaught|Unhandled)' "$work/chrome.log"; then |
| 31 | echo "FAIL uncaught exception in the browser:" |
| 32 | grep -oE 'CONSOLE:[0-9]+\] "[^"]*' "$work/chrome.log" | head -5 |
| 33 | exit 1 |
| 34 | fi |
| 35 | |
| 36 | python3 - "$work/shot.png" <<'EOF' |
| 37 | import sys |
| 38 | from PIL import Image |
| 39 | |
| 40 | im = Image.open(sys.argv[1]).convert('RGB') |
| 41 | w, h = im.size |
| 42 | # The canvas is the left ~70%; the right is the control panel. |
| 43 | canvas = im.crop((0, 0, int(w * 0.7), h)) |
| 44 | colors = canvas.getcolors(maxcolors=1 << 24) or [] |
| 45 | distinct = len(colors) |
| 46 | black = sum(n for n, c in colors if c == (0, 0, 0)) |
| 47 | total = canvas.size[0] * canvas.size[1] |
| 48 | |
| 49 | print(f"canvas {canvas.size[0]}x{canvas.size[1]}: {distinct} distinct colours, " |
| 50 | f"{100 * black / total:.1f}% pure black") |
| 51 | |
| 52 | # A blank/failed canvas is one flat colour. A real frame has the black |
| 53 | # interior of the set plus a smooth coloured exterior. |
| 54 | if distinct < 200: |
| 55 | sys.exit(f"FAIL canvas has only {distinct} distinct colours — nothing rendered") |
| 56 | if not (0.05 < black / total < 0.75): |
| 57 | sys.exit(f"FAIL black fraction {black / total:.2f} does not look like the set") |
| Replace V with Nim 472eb49 nandithebull 19h ago | 58 | print("ok Nim rendered a Mandelbrot frame in the browser") |
| Add a WebAssembly backend for the example 728acaa nandithebull 19h ago | 59 | EOF |