File size: 3,512 Bytes
42bbd85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/env bash
# Headless-Chrome smoke test for frontend.html.
#
# Two kinds of checks:
#   β€’ STATIC  β€” markup that's in the file regardless of rendering (buttons,
#     controls). Grepped straight from frontend.html β†’ 100% reliable.
#   β€’ DYNAMIC β€” proof the page actually rendered: CodeMirror mounted (its CDN/ESM
#     imports ran), the editor wrap was revealed and the textarea fallback hidden.
#     These need a real browser, so we render with headless Chrome.
#
# Only the dynamic half can flake (CDN timing), so the headless dump is retried
# until it's complete. Static checks never touch the browser.
#
# Usage: ./smoke-test.sh   (exit 0 = pass, 1 = fail)
set -euo pipefail
cd "$(dirname "$0")"

FILE="frontend.html"
src="$(cat "$FILE")"

CHROME="${CHROME:-/Applications/Google Chrome.app/Contents/MacOS/Google Chrome}"
[ -x "$CHROME" ] || { echo "βœ— Chrome not found at: $CHROME (set \$CHROME)"; exit 1; }

# Retry the dump until it's a COMPLETE render (has </html> AND the CodeMirror
# mount), up to 5 attempts β€” guards against partial/pre-render dumps.
dom=""
for attempt in 1 2 3 4 5; do
    dom="$("$CHROME" --headless --disable-gpu --no-sandbox \
            --virtual-time-budget=25000 \
            --dump-dom "file://$PWD/$FILE" 2>/dev/null)"
    if grep -q '</html>' <<<"$dom" && grep -q 'class="cm-editor' <<<"$dom"; then
        break
    fi
    [ "$attempt" -lt 5 ] && { echo "… incomplete render (attempt $attempt), retrying"; sleep 1; }
done

fail=0
chk() { # chk "<haystack>" "<label>" "<grep -E pattern>" "<want: yes|no>"
    # here-string (not echo|grep): with `set -o pipefail`, grep -q matching closes
    # the pipe early β†’ echo gets SIGPIPE β†’ the pipeline falsely reports failure.
    if grep -qE "$3" <<<"$1"; then found=yes; else found=no; fi
    if [ "$found" = "$4" ]; then echo "βœ“ $2"; else echo "βœ— $2 (wanted match=$4, got=$found)"; fail=1; fi
}
static() { chk "$src" "$1" "$2" "$3"; }   # grep the source file
dynamic(){ chk "$dom" "$1" "$2" "$3"; }   # grep the rendered DOM

echo "β€” dynamic (needs a real render) β€”"
dynamic "editor mounted (.cm-editor present)"      'class="cm-editor'                            yes
dynamic "line-number gutter rendered"              'class="cm-gutterElement'                     yes
dynamic "editor-wrap revealed by JS (not hidden)"  '<div id="editor-wrap" class="editor-wrap">' yes
dynamic "textarea fallback hidden by JS"           '<textarea id="code-fallback"[^>]*hidden'    yes

echo "β€” static (markup in the file) β€”"
static "language selector present"                 'id="lang-select"'                            yes
static "Copy / Clear buttons present"              'id="copy-btn".*|id="clear-btn"'              yes
static "Generate is compact (in action bar)"       '<button id="submit-btn" class="btn-primary"' yes
static "output toolbar present (Copy Mermaid)"     'id="copy-mmd-btn"'                            yes
static "SVG / PNG export buttons present"          'id="svg-btn".*|id="png-btn"'                 yes
static "export buttons disabled until a render"    '<button id="svg-btn"[^>]*disabled'           yes
static "theme toggle present"                      'id="theme-toggle"'                           yes
static "zoom controls present"                     'id="zoom-ctrl"'                              yes
static "flow-arrow cue present"                    'class="flow-arrow"'                          yes

echo
[ "$fail" -eq 0 ] && echo "PASS" || echo "FAIL"
exit "$fail"