#!/bin/bash # Regression test: start.sh dashboard bundle sync step. # # Validates the auto-sync that runs before `docker run` in start.sh: # 1. Bundles are coppied from /opt/dashcaddy/status/dist → /var/www/dashcaddy-status/dist # 2. sw.js is copied to /var/www/dashcaddy-status/sw.js # 3. index.html is copied to /var/www/dashcaddy-status/index.html # 4. Missing source dir is handled gracefully (WARN, no exit) # 5. Sync is idempotent — re-running doesn't clobber or duplicate set -u SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" FAILURES=0 pass() { echo " ✓ $1"; } fail() { echo " ✗ $1"; FAILURES=$((FAILURES + 1)); } # -------------------------------------------------------------------------- # Extract just the sync block from start.sh. The first call to `docker run` # marks the end of the sync section. # -------------------------------------------------------------------------- extract_sync_block() { awk ' /^# Sync the freshly-built dashboard bundle/ { capture=1 } /^docker run -d --restart unless-stopped/ { capture=0 } capture { print } ' "${SCRIPT_DIR}/../start.sh" } fresh_workdir() { local d; d="$(mktemp -d /tmp/dashcaddy-sync-test.XXXXXX)" mkdir -p "$d/src/dist" mkdir -p "$d/dst/dist" echo "$d" } cleanup() { rm -rf "$1"; } run_sync() { local workdir="$1" # Use absolute replacement paths that don't collide with sed prefixes. # Inject a unique sentinel into start.sh paths first, then replace that # sentinel with the test-specific paths. local src_sentinel="__SYNC_TEST_SRC__" local dst_sentinel="__SYNC_TEST_DST__" local SRC_DIST_DIR="${workdir}/src/dist" local DST_STATUS_DIR="${workdir}/dst" extract_sync_block | sed \ -e "s|/opt/dashcaddy/status/dist|${src_sentinel}|g" \ -e "s|/var/www/dashcaddy-status|${dst_sentinel}|g" \ -e "s|${src_sentinel}|${SRC_DIST_DIR}|g" \ -e "s|${dst_sentinel}|${DST_STATUS_DIR}|g" \ > /tmp/_sync_block.sh # shellcheck disable=SC1091 source /tmp/_sync_block.sh } # Test 1: Bundles + sw.js + index.html all get synced from a real source tree echo "Test 1: fresh source → files synced to status dir" WORKDIR="$(fresh_workdir)" SRC="${WORKDIR}/src/dist" echo 'console.log("core");' > "${SRC}/core.js" echo 'console.log("features");' > "${SRC}/features.js" echo 'self.addEventListener("fetch", ...)' > "${SRC}/sw.js" echo 'hi' > "${SRC}/index.html" run_sync "${WORKDIR}" if [ -f "${WORKDIR}/dst/dist/core.js" ]; then pass "core.js copied to status dir" else fail "core.js NOT copied" fi if [ -f "${WORKDIR}/dst/dist/features.js" ]; then pass "features.js copied" else fail "features.js NOT copied" fi if [ -f "${WORKDIR}/dst/sw.js" ]; then pass "sw.js copied (NOT under dist/)" else fail "sw.js NOT copied" fi if [ -f "${WORKDIR}/dst/index.html" ]; then pass "index.html copied" else fail "index.html NOT copied" fi cleanup "${WORKDIR}" # Test 2: Missing source dir → WARN, no exit, no crash, no destinations created echo echo "Test 2: source dir missing → WARN, no exit" WORKDIR="$(fresh_workdir)" # SRC intentionally NOT created run_sync "${WORKDIR}" # If we reach here without an exit code propagating, we passed if [ -z "$(ls -A "${WORKDIR}/dst/dist" 2>/dev/null)" ]; then pass "no files copied when source missing" else fail "files copied when source was missing — should be no-op" fi cleanup "${WORKDIR}" # Test 3: Re-running syncs (idempotent — files overwritten with same content) echo echo "Test 3: idempotency (re-sync overwrites with same content)" WORKDIR="$(fresh_workdir)" SRC="${WORKDIR}/src/dist" echo 'core-v1' > "${SRC}/core.js" run_sync "${WORKDIR}" echo 'core-v2' > "${SRC}/core.js" # mutate source run_sync "${WORKDIR}" if [ "$(cat "${WORKDIR}/dst/dist/core.js")" = "core-v2" ]; then pass "second sync picked up the latest source" else fail "second sync did not update" fi cleanup "${WORKDIR}" # Test 4: set -e propagation — a single file-level failure doesn't take down the script echo echo "Test 4: set -e does not kill container start when sync hits a permission error" WORKDIR="$(fresh_workdir)" SRC="${WORKDIR}/src/dist" echo 'core' > "${SRC}/core.js" DST="${WORKDIR}/dst/dist" chmod 555 "${DST}" # write-protected dest → cp -f would fail # shellcheck disable=SC1091 set -e run_sync "${WORKDIR}" EXIT=$? set +e chmod 755 "${DST}" 2>/dev/null cleanup "${WORKDIR}" if [ "$EXIT" -eq 0 ]; then pass "sync step survives a permission-denied dest" else fail "set -e propagated a sync failure (exit ${EXIT}); would prevent container from starting" fi rm -f /tmp/_sync_block.sh echo if [ "$FAILURES" -eq 0 ]; then echo "All sync regression tests passed." exit 0 fi echo "${FAILURES} test(s) failed." exit 1