test: phase 33 gate, layer, consumer and admin stages
- layers: node --test runs checked with a TAP detector (self-tested), every vue-seo-layer smoke, guard:check and purge:check, all five journal expectation files (postTitleTag h1 and p), the journal purge checks and check-git-install.sh --self-test - consumers: the 33-12 and 33-13 app patches pass git apply --check, and the 33-14 demo locale patches apply on top of the 33-12 ones in scratch worktrees
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
# plugins, the four Nuxt layers and the applications that consume them.
|
||||
#
|
||||
# Stages:
|
||||
# self-test the go test -json and vitest detectors on planted output, a
|
||||
# self-test the go test -json, vitest and TAP detectors on planted output, a
|
||||
# failing go test in a planted module, the marker rule on a
|
||||
# planted repository, the missing-repository failure, the docker
|
||||
# NOT RUN rule on a faked host, and the additive comparison on
|
||||
@@ -18,12 +18,18 @@
|
||||
# required name (*_UNIT_TESTS); npm run test (vitest) in
|
||||
# sm-seo-plugin and sm-journal-plugin.
|
||||
# layers vue-seo-layer, vue-journal-layer, vue-menu-layer and
|
||||
# vue-faq-layer: npm run test, npm run build:playground and the
|
||||
# layer's SSR smoke; node testing/guard-check.mjs in
|
||||
# vue-seo-layer (the build-guard fixtures).
|
||||
# vue-faq-layer: npm run test (node --test, an all-passing TAP
|
||||
# summary), npm run build:playground and the layer's SSR
|
||||
# smokes; in vue-seo-layer guard:check (the build-guard
|
||||
# fixtures) and purge:check; in vue-journal-layer every
|
||||
# expectation file (expect-acme-title-h1 and -title-p with
|
||||
# NUXT_PUBLIC_JOURNAL_POST_TITLE_TAG), the purge checks and
|
||||
# check-git-install.sh --self-test.
|
||||
# consumers sm-demo-app, sm-grzybyfunkcjonalne-app, sm-summercmsio-app and
|
||||
# sm-bm-app: the workspace check and go build ./...; npm run
|
||||
# build in each Nuxt app (vue-*/ with a build script).
|
||||
# build in each Nuxt app (vue-*/ with a build script); the
|
||||
# 33-12 and 33-13 app patches pass git apply --check, and the
|
||||
# 33-14 demo locale patches apply on top of the 33-12 ones.
|
||||
# docker Docker host only: the Postgres suites (go test ./... without
|
||||
# -short) of the three Go plugins with the phase's suites by
|
||||
# required name (*_DOCKER_TESTS; TestChromeRenderer too when a
|
||||
@@ -404,6 +410,46 @@ npm_vitest() {
|
||||
rm -f "$log"
|
||||
}
|
||||
|
||||
# detect_tap reads a node --test --test-reporter=tap run. Exit 1 a failed
|
||||
# test ("not ok", "# fail" or "# cancelled" above 0), 2 skipped or todo
|
||||
# tests, 3 no all-passing summary.
|
||||
detect_tap() {
|
||||
python3 - "$1" <<'PY'
|
||||
import re, sys
|
||||
text = open(sys.argv[1], encoding="utf-8", errors="replace").read()
|
||||
text = re.sub(r"\x1b\[[0-9;]*m", "", text)
|
||||
counts = {k: int(v) for k, v in re.findall(r"^# (tests|pass|fail|skipped|todo|cancelled) (\d+)\s*$", text, re.M)}
|
||||
if re.search(r"^\s*not ok\b", text, re.M) or counts.get("fail", 0) > 0 or counts.get("cancelled", 0) > 0:
|
||||
print("refuse: TAP reports failed tests", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if counts.get("skipped", 0) > 0 or counts.get("todo", 0) > 0 or re.search(r"^\s*ok .*# (SKIP|TODO)\b", text, re.M | re.I):
|
||||
print("refuse: TAP reports skipped or todo tests", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
if "fail" not in counts or counts.get("pass", 0) == 0 or counts.get("tests", -1) != counts.get("pass"):
|
||||
print("refuse: no all-passing TAP summary", file=sys.stderr)
|
||||
sys.exit(3)
|
||||
PY
|
||||
}
|
||||
|
||||
# node_tap DIR runs npm run test (node --test with the TAP reporter) in DIR
|
||||
# and requires an all-passing TAP summary.
|
||||
node_tap() {
|
||||
local dir="$1" log rc=0 dc=0
|
||||
require_script "$dir" test
|
||||
log="$(mktemp)"
|
||||
npm --prefix "$dir" run test >"$log" 2>&1 || rc=$?
|
||||
detect_tap "$log" || dc=$?
|
||||
if [[ "$rc" -ne 0 || "$dc" -ne 0 ]]; then
|
||||
grep -E '^\s*not ok|# (fail|skipped|todo)|Error' "$log" | head -n 40 >&2 || true
|
||||
tail -n 20 "$log" >&2
|
||||
rm -f "$log"
|
||||
echo "refuse: npm run test in $dir (test=$rc detect=$dc)" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "tap: $dir $(grep -E '^# (tests|pass|fail) ' "$log" | tr '\n' ' ')"
|
||||
rm -f "$log"
|
||||
}
|
||||
|
||||
# require_script DIR NAME refuses DIR without node_modules or without the
|
||||
# npm script NAME in its package.json.
|
||||
require_script() {
|
||||
@@ -515,6 +561,25 @@ run_self_test() {
|
||||
expect_detector detect_vitest failed 1 ' Test Files 1 failed | 1 passed (2)
|
||||
Tests 1 failed | 16 passed (17)'
|
||||
expect_detector detect_vitest no-summary 3 ' ✓ tests/a.test.ts (12 tests) 15ms'
|
||||
local tap='TAP version 13
|
||||
ok 1 - a
|
||||
ok 2 - b
|
||||
1..2
|
||||
# tests 2
|
||||
# suites 0
|
||||
# pass 2
|
||||
# fail 0
|
||||
# cancelled 0
|
||||
# skipped 0
|
||||
# todo 0'
|
||||
expect_detector detect_tap pass 0 "$tap"
|
||||
expect_detector detect_tap not-ok 1 "${tap/ok 2 - b/not ok 2 - b}"
|
||||
expect_detector detect_tap fail-count 1 "${tap/\# fail 0/\# fail 1}"
|
||||
expect_detector detect_tap skipped 2 "${tap/\# skipped 0/\# skipped 1}"
|
||||
expect_detector detect_tap skip-directive 2 "${tap/ok 2 - b/ok 2 - b # SKIP not here}"
|
||||
expect_detector detect_tap no-summary 3 'TAP version 13
|
||||
ok 1 - a'
|
||||
expect_detector detect_tap zero 3 "$(printf '# tests 0\n# pass 0\n# fail 0')"
|
||||
|
||||
local tmp
|
||||
tmp="$(mktemp -d)"
|
||||
@@ -695,14 +760,29 @@ run_layers() {
|
||||
local layer
|
||||
require_all "Nuxt layer" "$SEO_LAYER" "$JOURNAL_LAYER" "$MENU_LAYER" "$FAQ_LAYER"
|
||||
for layer in "$SEO_LAYER" "$JOURNAL_LAYER" "$MENU_LAYER" "$FAQ_LAYER"; do
|
||||
npm_vitest "$layer"
|
||||
node_tap "$layer"
|
||||
npm_script "$layer" build:playground
|
||||
done
|
||||
# vue-seo-layer: every smoke expectation (the layer on, off, the CMS
|
||||
# down, without the 404 token, with drift), the build-guard fixtures
|
||||
# and the purge checks.
|
||||
npm_script "$SEO_LAYER" smoke:ssr
|
||||
node_run "$JOURNAL_LAYER" testing/smoke-ssr.mjs --output .playground/.output --fixtures testing/fixtures/acme --expect testing/expect-acme.txt
|
||||
npm_script "$SEO_LAYER" guard:check
|
||||
npm_script "$SEO_LAYER" purge:check
|
||||
# vue-journal-layer: the acme expectations, the post title forced to h1
|
||||
# and to p (postTitleTag), the link hint and the breadcrumbs off, the
|
||||
# purge checks and the git-install lockfile reading.
|
||||
local journal_smoke=(testing/smoke-ssr.mjs --output .playground/.output --fixtures testing/fixtures/acme)
|
||||
node_run "$JOURNAL_LAYER" "${journal_smoke[@]}" --expect testing/expect-acme.txt
|
||||
node_run "$JOURNAL_LAYER" "${journal_smoke[@]}" --expect testing/expect-acme-title-h1.txt --env NUXT_PUBLIC_JOURNAL_POST_TITLE_TAG=h1
|
||||
node_run "$JOURNAL_LAYER" "${journal_smoke[@]}" --expect testing/expect-acme-title-p.txt --env NUXT_PUBLIC_JOURNAL_POST_TITLE_TAG=p
|
||||
node_run "$JOURNAL_LAYER" "${journal_smoke[@]}" --expect testing/expect-acme-hint-off.txt --env NUXT_PUBLIC_SEO_LINKS_NEW_TAB_HINT=false
|
||||
node_run "$JOURNAL_LAYER" "${journal_smoke[@]}" --expect testing/expect-acme-breadcrumbs-off.txt --env NUXT_PUBLIC_JOURNAL_BREADCRUMBS=false
|
||||
node_run "$JOURNAL_LAYER" testing/purge-check.mjs --output .playground/.output --fixtures testing/fixtures/acme --kind post --slug hello-acme --path /blog/hello-acme
|
||||
node_run "$JOURNAL_LAYER" testing/purge-token-check.mjs --output .playground/.output --fixtures testing/fixtures/acme --path /blog/hello-acme
|
||||
(cd "$JOURNAL_LAYER" && bash scripts/check-git-install.sh --self-test)
|
||||
npm_script "$MENU_LAYER" smoke:ssr
|
||||
npm_script "$FAQ_LAYER" smoke:ssr
|
||||
node_run "$SEO_LAYER" testing/guard-check.mjs
|
||||
echo "phase33 layers passed"
|
||||
}
|
||||
|
||||
@@ -718,9 +798,54 @@ run_consumers() {
|
||||
npm_script "$(dirname "$pkg")" build
|
||||
done
|
||||
done
|
||||
# The app patches of plans 33-12, 33-13 and 33-14 apply to the apps as
|
||||
# committed; 33-14's demo locale patches apply on top of the 33-12 demo
|
||||
# patches (checked in scratch worktrees).
|
||||
patch_check "$DEMO_APP" 33-12-sm-demo-app.patch
|
||||
patch_check "$DEMO_APP/vue-demo-app" 33-12-vue-demo-app.patch
|
||||
patch_check "$SUMMERCMSIO_APP" 33-12-sm-summercmsio-app.patch
|
||||
patch_check "$SUMMERCMSIO_APP/vue-summercmsio-app" 33-12-vue-summercmsio-app.patch
|
||||
patch_check "$GRZYBY_APP" 33-13-sm-grzybyfunkcjonalne-app.patch
|
||||
patch_check "$GRZYBY_APP/vue-grzybyfunkcjonalne-app" 33-13-vue-grzybyfunkcjonalne-app.patch
|
||||
scratch_init
|
||||
stacked_patch_check "$DEMO_APP/vue-demo-app" 33-12-vue-demo-app.patch 33-14-vue-demo-app-locale.patch
|
||||
if [[ -f "$PHASE_DIR/33-14-sm-demo-app-locale.patch" ]]; then
|
||||
stacked_patch_check "$DEMO_APP" 33-12-sm-demo-app.patch 33-14-sm-demo-app-locale.patch
|
||||
fi
|
||||
echo "phase33 consumers passed"
|
||||
}
|
||||
|
||||
# PHASE_DIR holds the app patches.
|
||||
PHASE_DIR="$ROOT/.planning/phases/33-seo-output-audit-and-content"
|
||||
|
||||
# patch_check REPO PATCH runs git apply --check of a phase patch in REPO
|
||||
# (--allow-empty: an empty patch, such as summercms.io's Go side, passes).
|
||||
patch_check() {
|
||||
local repo="$1" patch="$PHASE_DIR/$2"
|
||||
require_dir "$repo" "patch target"
|
||||
require_file "$patch" "app patch"
|
||||
if ! git -C "$repo" apply --check --allow-empty "$patch"; then
|
||||
echo "refuse: $2 does not apply to $repo" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "patch: $2 applies to $repo"
|
||||
}
|
||||
|
||||
# stacked_patch_check REPO BASE PATCH applies BASE in a scratch worktree of
|
||||
# REPO's HEAD and runs git apply --check of PATCH on top of it.
|
||||
stacked_patch_check() {
|
||||
local repo="$1" base="$PHASE_DIR/$2" patch="$PHASE_DIR/$3" wt
|
||||
require_file "$base" "app patch"
|
||||
require_file "$patch" "app patch"
|
||||
wt="$SCRATCH/stack-$(basename "$repo")-$RANDOM"
|
||||
add_worktree "$repo" "$wt" HEAD
|
||||
if ! git -C "$wt" apply --allow-empty "$base" || ! git -C "$wt" apply --check --allow-empty "$patch"; then
|
||||
echo "refuse: $3 does not apply to $repo with $2" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "patch: $3 applies to $repo on top of $2"
|
||||
}
|
||||
|
||||
docker_up() {
|
||||
command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user