Files
runway/crates/runway-caldav/tests/baikal/run.sh
T
connor c4e8ede28c Add the events API
One path with an EditScope on the write verbs. v1 had a second parallel
tree at /api/calendar/events/series/* -- 1,165 lines mostly duplicating
the non-series handlers, dispatching on string literals in 53 places where
a typo was a runtime fallthrough.

What a scoped edit means to the stored .ics lives in runway-core::series,
pure and tested without a server, because that is the subtle part and v1
shipped it with no coverage at all. Editing one occurrence writes an
override and no EXDATE: an EXDATE says the occurrence does not happen, an
override says it happens differently, and writing both is contradictory.
Deleting one writes the EXDATE and removes any override that named it.

Splitting a series divides its bound rather than dropping it. Six weekly
occurrences split at the third become two plus four, not two plus
forever -- the count is what the person asked for and it should survive
being cut. Overrides after the split move to the new series; moving a
whole series shifts its overrides' RECURRENCE-IDs by the same amount
instead of leaving them pointing at occurrences that no longer exist.

Every write states a precondition. There is no unconditional path: an
update without an ETag is refused, and a stale one is a conflict rather
than a silent overwrite. UIDs are minted server-side, because a
client-supplied one could collide with and replace an unrelated event.

Reads use time-range and fan out across calendars concurrently. Zones that
cannot be resolved are reported in the response instead of being rendered
as though they were fine.

Two tests found real bugs: sub-second timestamps cannot survive
iCalendar's one-second resolution, and splitting at the first occurrence
was dropping the recurrence rule and quietly turning a series into a
single event.
2026-08-26 17:07:38 -04:00

61 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Run the CalDAV integration tests against a throwaway Baikal.
#
# Starts a container, walks it through the install wizard, runs the live test
# suite against it, and tears it down again. Nothing touches a real calendar.
#
# crates/runway-caldav/tests/baikal/run.sh # start, test, stop
# KEEP=1 crates/runway-caldav/tests/baikal/run.sh # leave it running
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
NAME="${NAME:-runway-baikal}"
PORT="${PORT:-8800}"
IMAGE="${IMAGE:-docker.io/ckulka/baikal:nginx}"
USERNAME="testuser"
PASSWORD="testpassword"
runtime() {
if command -v podman >/dev/null 2>&1; then echo podman
elif command -v docker >/dev/null 2>&1; then echo docker
else echo "need podman or docker" >&2; exit 1
fi
}
RUNTIME="$(runtime)"
cleanup() {
if [ "${KEEP:-0}" != "1" ]; then
"$RUNTIME" rm -f "$NAME" >/dev/null 2>&1 || true
else
echo "container $NAME left running on port $PORT"
fi
}
trap cleanup EXIT
"$RUNTIME" rm -f "$NAME" >/dev/null 2>&1 || true
"$RUNTIME" run -d --rm --name "$NAME" -p "$PORT:80" "$IMAGE" >/dev/null
echo "started $NAME ($IMAGE) on port $PORT"
# Baikal needs a moment before PHP answers.
for _ in $(seq 1 60); do
if [ "$(curl -sS -o /dev/null -w '%{http_code}' -L "http://localhost:$PORT/" 2>/dev/null)" = "200" ]; then
break
fi
sleep 1
done
python3 "$HERE/setup.py" "http://localhost:$PORT" "$USERNAME" "$PASSWORD"
export RUNWAY_CALDAV_URL="http://localhost:$PORT/dav.php/"
export RUNWAY_CALDAV_USER="$USERNAME"
export RUNWAY_CALDAV_PASSWORD="$PASSWORD"
# Turns a silent skip into a failure: see the note in live.rs.
export RUNWAY_REQUIRE_CALDAV=1
# Both suites: the CalDAV client against the server, and the backend's own
# login flow against it. Skipped tests report as "ok", so the only way to know
# they ran is to run them here.
cargo test -p runway-caldav --test live -- --test-threads=1 "$@"
cargo test -p runway-server --test auth -- --test-threads=1 "$@"
cargo test -p runway-server --test events -- --test-threads=1 "$@"