Files
ElyOffice/tests/scripts/mark-session.sh
T
ZacharyZhang-NY b7fca0146d Ely Office: six offline-first desktop apps in Rust and GPUI
ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git),
ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
2026-10-08 21:20:08 -04:00

167 lines
5.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# QA-21: a save keeps bytes no edit touched.
set -euo pipefail
root=$(cd "$(dirname "$0")/../.." && pwd)
[ "$(uname)" = Darwin ] || { echo "SKIP: macOS only"; exit 0; }
[ -d "${ELY_CEF:-$root/engines/cef}/Chromium Embedded Framework.framework" ] || {
echo "SKIP: no CEF; run scripts/fetch-cef.sh"
exit 0
}
command -v npm >/dev/null || { echo "SKIP: no npm"; exit 0; }
work=$(mktemp -d)
app=
trap 'if [ -n "$app" ]; then kill "$app" 2>/dev/null || true; wait "$app" 2>/dev/null || true; fi; chmod -R u+rw "$work"; rm -rf "$work"' EXIT
fail() {
echo "FAIL: $*" >&2
exit 1
}
"$root/scripts/build-mark-content.sh" >"$work/build" 2>&1 || fail "build: $(tail -n 5 "$work/build")"
cargo build -q -p ely-mark --manifest-path "$root/Cargo.toml"
swiftc -O -o "$work/press" "$root/tests/scripts/ax-press.swift"
waits() {
for _ in $(seq 200); do
grep -qF "$1" "$work/err" && return 0
kill -0 "$app" 2>/dev/null || break
sleep 0.25
done
fail "never saw '$1': $(grep -E 'mark|office' "$work/err" | tail -n 5)"
}
# Starts ElyMark on `file`; it must show visually.
launch() {
: >"$work/err"
ELY_LOG=info ELY_LOCALE=en ELY_NO_DIALOG=1 HOME="$work" XDG_DATA_HOME="$work/data" \
"$root/target/debug/ely-mark" "$1" >"$work/out" 2>"$work/err" &
app=$!
}
shown() {
waits "mark: shown as"
grep -qF 'mark: shown as "visual", fallback false' "$work/err" ||
fail "not shown visually: $(grep 'mark: shown' "$work/err")"
osascript -e "tell application \"System Events\" to set frontmost of (first process whose unix id is $app) to true" \
-e 'delay 0.5' >/dev/null
}
type() { osascript -e "tell application \"System Events\" to $1" -e 'delay 1' >/dev/null; }
save_quit() {
type 'keystroke "s" using command down'
waits "office: saved"
osascript -e 'tell application "System Events" to keystroke "q" using command down' >/dev/null
for _ in $(seq 40); do
kill -0 "$app" 2>/dev/null || break
sleep 0.25
done
! kill -0 "$app" 2>/dev/null || fail "ElyMark did not quit"
app=
! grep -q "panicked" "$work/err" || fail "panics: $(grep -m3 panicked "$work/err")"
}
# Saves `name` after `keys`; it must equal `want`.
check() {
local name=$1 text=$2 keys=$3 want=$4
printf '%s' "$text" >"$work/$name"
launch "$work/$name"
shown
[ -z "$keys" ] || type "$keys"
save_quit
[ "$(cat "$work/$name"; echo .)" = "$want." ] || fail "$name saved as: $(cat "$work/$name")"
}
# BOM, CRLF, front matter and syntax Milkdown rewrites.
python3 - "$work/keep.md" <<'PY'
import sys
text = """---
title: Keep
tags: [a, b]
---
First paragraph.
Setext
======
1) paren list
2) second
* star
* list
<div align="center">
<b>html</b>
</div>
See [[Wiki Link]], ~sub~ and [a ref][r].
next line
[r]: https://example.com "T"
Last paragraph.
"""
open(sys.argv[1], "wb").write(b"\xef\xbb\xbf" + text.replace("\n", "\r\n").encode())
PY
cp "$work/keep.md" "$work/plain.md"
launch "$work/plain.md"
shown
save_quit
cmp -s "$work/keep.md" "$work/plain.md" || fail "an unedited save changed bytes"
cp "$work/keep.md" "$work/edited.md"
launch "$work/edited.md"
shown
type 'keystroke "x"'
save_quit
python3 - "$work/keep.md" "$work/edited.md" <<'PY'
import sys
before, after = (open(path, "rb").read() for path in sys.argv[1:])
want = before.replace(b"First paragraph.", b"xFirst paragraph.", 1)
if after != want:
sys.exit(f"FAIL: the edit rewrote more than its block:\n{after!r}")
PY
# Blocks Milkdown would rewrite are edited as raw text.
check wiki.md $'Alpha with [[Wiki Link]].\n' 'keystroke "x"' $'xAlpha with [[Wiki Link]].\n'
quote=$'> First.\n>\n> Setext\n> ======\n>\n> Last with [[Wiki]].\n'
check quote.md "$quote" 'keystroke "x"' "x$quote"
check defs.md $'[r]: https://example.com\n' 'keystroke "x"' $'x[r]: https://example.com\n'
# Deleting forward at a hidden definition moves nothing.
gap=$'Alpha.\n\n[r]: /path " T " \n\nBeta.\n\nTail.\n'
check gap.md "$gap" 'key code 119' "$gap"
printf '%s' "$gap" >"$work/gap2.md"
launch "$work/gap2.md"
shown
type 'key code 119'
type 'key code 117'
save_quit
[ "$(cat "$work/gap2.md"; echo .)" = "$gap." ] || fail "the definition moved: $(cat "$work/gap2.md")"
# A reloaded page's edits still save.
printf 'Alpha.\n' >"$work/crash.md"
launch "$work/crash.md"
shown
# Two versions first: the new page counts from one.
type 'keystroke "x"'
type 'keystroke "z"'
pkill -P "$app" -f -- "--type=renderer" || fail "no renderer to stop"
pressed=
for _ in $(seq 40); do
[ "$("$work/press" "$app" Reload)" = pressed ] && pressed=1 && break
sleep 0.25
done
[ -n "$pressed" ] || fail "no Reload button"
for _ in $(seq 80); do
[ "$(grep -c 'mark: shown as' "$work/err")" -ge 2 ] && break
sleep 0.25
done
osascript -e "tell application \"System Events\" to set frontmost of (first process whose unix id is $app) to true" >/dev/null
type 'keystroke "y"'
save_quit
grep -q "y" "$work/crash.md" || fail "an edit after reload was lost: $(cat "$work/crash.md")"
# An unreadable file says so; no password is asked.
printf 'secret\n' >"$work/denied.md"
chmod 000 "$work/denied.md"
launch "$work/denied.md"
waits "did not open"
grep -q "Permission denied" "$work/err" || fail "the reason is missing: $(grep 'did not open' "$work/err")"
! grep -q "locked" "$work/err" || fail "taken for a locked file"
kill "$app"
app=
echo "ok: mark session"