Files
Ustagammon/tests/test_web.sh

96 lines
4.5 KiB
Bash

#!/usr/bin/env bash
# Teste l'application web (app/, ADR 0009), dans l'image ustagammon/web :
# - tests unitaires du domaine (faux moteur) et partie complète sur le vrai
# moteur WebAssembly (node:test) ;
# - scénarios de docs/scenarios/ exécutés par Cucumber sur le domaine branché
# au vrai moteur (ADR 0008) ;
# - règles d'architecture (dependency-cruiser, ADR 0007), et preuve qu'une
# violation volontaire de chaque règle est bien détectée ;
# - export SGF : des parties jouées sur le vrai moteur, exportées, relues par
# le GNU Backgammon de référence, qui doit y retrouver les positions du
# journal (tests/sgf/check.py).
#
# Lance `make engine-wasm` et `make web` (sans effet si tout est à jour).
set -euo pipefail
cd "$(dirname "$0")/.."
image="${WEB_IMAGE:?lancer via make test}"
# Lancé depuis `make test` : repartir d'un make indépendant du make parent.
unset MAKEFLAGS MFLAGS MAKELEVEL
make engine-wasm >/dev/null
make web >/dev/null
errors=0
report() {
echo " $1"
errors=$((errors + 1))
}
# Lance une commande des outils web, dépôt monté sous /src ; le premier
# argument est le dossier de travail, relatif au dépôt.
web() {
local dir="$1"
shift
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/src" -w "/src/$dir" "$image" "$@"
}
web . node --test --test-reporter=dot 'build/web/tests/**/*.test.js' \
|| report "tests unitaires ou partie complète en échec (voir ci-dessus)"
web . cucumber-js --format summary --import 'build/web/tests/steps/*.js' docs/scenarios/*.feature \
|| report "scénarios en échec (voir ci-dessus)"
# Export SGF relu par gnubg de bureau. Le script Python de gnubg ne
# transmet pas de code de sortie : sa dernière ligne donne le verdict.
samples=build/sgf-samples
rm -rf "$samples"
if ! docker image inspect "${REFERENCE_IMAGE:?lancer via make test}" >/dev/null 2>&1; then
report "gnubg de référence absent : lancer d'abord make setup"
elif ! web . node build/web/tests/tools/sgf-samples.js "$samples" >/dev/null; then
report "parties d'exemple SGF non produites (voir ci-dessus)"
else
output="$(docker run --rm --user "$(id -u):$(id -g)" -e HOME=/tmp \
-v "$PWD/$samples:/sgf:ro" -v "$PWD/tests/sgf:/check:ro" "$REFERENCE_IMAGE" \
gnubg --tty --quiet --no-rc --python=/check/check.py 2>&1)" || true
if ! grep -q '^SGF-RESULTAT OK$' <<<"$output"; then
grep -E '^(ÉCHEC|aucun|Traceback| File|[A-Za-z]*Error)' <<<"$output" || true
report "export SGF : gnubg ne retrouve pas les positions du journal"
fi
fi
web app depcruise --config .dependency-cruiser.cjs src tests \
|| report "règles d'architecture non respectées (voir ci-dessus)"
# Violations volontaires, dans un dossier jetable sous build/ : chaque règle
# doit être signalée par dependency-cruiser.
fixture=build/web-violations
rm -rf "$fixture"
mkdir -p "$fixture/src/domain" "$fixture/src/engine" "$fixture/src/ui" "$fixture/src/storage"
cp app/tsconfig.json "$fixture/"
echo 'export const main = 1;' >"$fixture/src/main.ts"
echo 'export const store = 1;' >"$fixture/src/storage/store.ts"
echo 'import { store } from "../storage/store.js"; export const f = store;' >"$fixture/src/ui/uses-storage.ts"
echo 'import { e } from "../ui/loop-b.js"; export const g = e;' >"$fixture/src/storage/uses-ui.ts"
echo 'import { main } from "../main.js"; export const h = main;' >"$fixture/src/ui/uses-main.ts"
echo 'import { engine } from "../engine/adapter.js"; export const a = engine;' >"$fixture/src/domain/uses-engine.ts"
echo 'import { readFileSync } from "node:fs"; export const b = readFileSync;' >"$fixture/src/domain/uses-node.ts"
echo 'export const engine = 1;' >"$fixture/src/engine/adapter.ts"
echo 'import { engine } from "../engine/adapter.js"; export const c = engine;' >"$fixture/src/ui/uses-engine.ts"
echo 'import { e } from "./loop-b.js"; export const d = e;' >"$fixture/src/ui/loop-a.ts"
echo 'import { d } from "./loop-a.js"; export const e = d;' >"$fixture/src/ui/loop-b.ts"
output="$(web "$fixture" depcruise --config /src/app/.dependency-cruiser.cjs src 2>&1)" \
&& report "dependency-cruiser accepte des violations volontaires"
for rule in domain-is-pure ui-does-not-call-engine only-main-assembles nothing-imports-main no-circular; do
grep -q "$rule" <<<"$output" || report "violation volontaire de $rule non détectée"
done
grep -q 'uses-node' <<<"$output" || report "import de Node dans le domaine non détecté"
for file in uses-storage uses-ui; do
grep -q "only-main-assembles: src/[a-z]*/$file" <<<"$output" \
|| report "assemblage hors de main.ts non détecté ($file)"
done
rm -rf "$fixture"
[ "$errors" -eq 0 ]