feat(course): audit fixes and twelve extensions (Modules 7b, 12, 13)
Audit pass: - Frame rule counts frames since the last move, so every step lasts exactly movesEvery(score) frames, also right after a speed-up - clampTime + MAX_GAP_MS: a hidden tab no longer replays the whole gap - Pong Restart keeps held keys - Fact corrections (mulberry32 output coverage, Haskell IO, uniform) - New fixture cases from a mutation analysis Extensions (all three tracks, shared fixtures, course text): - Turn queue (Exercise 10.6), persisted high score (10.7), replay viewer (10.8), play() end-to-end helper (9.5) - Optional State (4.7) and optional Module 7b, stack-safe IO - Module 12, property-based testing with generators, shrinking, invariants and a model-based oracle - Module 13, Conway's Life with a Click event - JS type checking via jsconfig, JSDoc and types.d.ts - Maintainer tools: scripts/mutate.mjs, scripts/typecheck-js.sh, Playwright end-to-end suite (e2e/, scripts/e2e.sh) Docs: docs/contract.md is the canonical contract; specs and build log under docs/superpowers. Verified: JS 728, Scala 689, F# 691 unit tests; stubs and progression M01-M13 and M07b; 176 end-to-end tests on Chromium and WebKit. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
1 parent
876f5aabb1
commit
edd57f0148
253 files changed
+21753
-503
No files matched your search
+31
-3
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# Usage: scripts/check-stubs.sh <js|scala|fsharp>
|
||||
# Runs each module M01..M11 that has tests against the stubs in src/. Fails if any module's tests pass,
|
||||
# Runs each module M01..M13 (and the optional M07b) that has tests against the stubs in src/. Fails if any module's tests pass,
|
||||
# and also fails (exit 2) on tooling/build errors, so a broken toolchain can never look like "stubs fail".
|
||||
set -uo pipefail
|
||||
track="${1:?usage: check-stubs.sh <js|scala|fsharp>}"
|
||||
@@ -32,11 +32,39 @@ tests_failed() {
|
||||
esac
|
||||
}
|
||||
|
||||
# Modules in course order; "07b" is the optional Module 7b.
|
||||
modules="01 02 03 04 05 06 07 07b 08 09 10 11 12 13"
|
||||
|
||||
# Scala's `./test.sh M07` (munit glob "*M07*") and F#'s (Expecto --filter-test-list, a substring) also select the
|
||||
# M07b tests. Their failures would hide an M07 that wrongly passes, so for such a module run the tests in a temp
|
||||
# copy without the longer-tagged modules' test files (F#: also without their line in tests/Snake.Tests.fsproj).
|
||||
run_module() {
|
||||
local n="$1" longer="" t f tmp
|
||||
if [ "$track" != js ]; then
|
||||
for t in $modules; do [[ "$t" == "$n"?* ]] && has "$t" && longer="$longer $t"; done
|
||||
fi
|
||||
if [ -z "$longer" ]; then (cd "$dir" && ./test.sh "M$n" 2>&1); return; fi
|
||||
tmp="$(mktemp -d)"
|
||||
tar -C "$repo" --exclude=.git --exclude=node_modules --exclude=bin --exclude=obj \
|
||||
--exclude=.scala-build --exclude=.bsp --exclude=.superpowers -cf - . | tar -C "$tmp" -xf -
|
||||
for t in $longer; do
|
||||
case "$track" in
|
||||
scala) rm -f "$tmp"/scala/test/M"$t"*.test.scala ;;
|
||||
fsharp) for f in "$tmp"/fsharp/tests/M"$t"*.fs; do
|
||||
rm -f "$f"; sed -i "/Include=\"$(basename "$f")\"/d" "$tmp/fsharp/tests/Snake.Tests.fsproj"
|
||||
done ;;
|
||||
esac
|
||||
done
|
||||
(cd "$tmp/$track" && ./test.sh "M$n" 2>&1); local rc=$?
|
||||
rm -rf "$tmp"
|
||||
return $rc
|
||||
}
|
||||
|
||||
status=0
|
||||
for n in 01 02 03 04 05 06 07 08 09 10 11; do
|
||||
for n in $modules; do
|
||||
m="M$n"
|
||||
if ! has "$n"; then echo "$m: no tests"; continue; fi
|
||||
out="$(cd "$dir" && ./test.sh "$m" 2>&1)"; rc=$?
|
||||
out="$(run_module "$n")"; rc=$?
|
||||
out="$(sed $'s/\x1b\\[[0-9;?]*[A-Za-z]//g' <<<"$out")"
|
||||
if [ $rc -eq 0 ]; then
|
||||
echo "$m: FAIL (tests pass against stubs)"; status=1
|
||||
|
||||
Reference in new issue
Block a user