chore: bump kanban 0.1.0 -> 0.2.0 + e2e smoke (issue 0128)

- app.md: descripcion, e2e_checks smoke_files, doc Archivos, capability growth log
- .gitignore: uploads/
- e2e/files_smoke.sh: build, login, upload PNG, list, serve, delete
This commit is contained in:
2026-05-27 10:52:06 +02:00
parent ac5f016e7e
commit 489d2bbef6
3 changed files with 98 additions and 3 deletions
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/env bash
# Issue 0128 — smoke test of card file attachments.
# Builds kanban (assumes ./kanban present or builds it), boots on ephemeral port,
# exercises POST upload, GET list, GET serve, DELETE, GET list-after-delete.
# Exits 0 on success, non-zero on any failure.
set -euo pipefail
PORT=${PORT:-18095}
BASE="http://127.0.0.1:${PORT}"
DB=$(mktemp /tmp/kanban_files_smoke.XXXXXX.db)
COOKIE=$(mktemp /tmp/kanban_files_smoke.cookie.XXXXXX)
UPLOAD_DIR=$(dirname "$DB")/uploads
PNG=$(mktemp /tmp/kanban_files_smoke.XXXXXX.png)
PID_FILE=$(mktemp /tmp/kanban_files_smoke.pid.XXXXXX)
cleanup() {
if [ -s "$PID_FILE" ]; then
kill "$(cat "$PID_FILE")" 2>/dev/null || true
fi
rm -f "$DB" "$DB-shm" "$DB-wal" "$COOKIE" "$PNG" "$PID_FILE"
rm -rf "$UPLOAD_DIR"
}
trap cleanup EXIT
# Build if missing.
if [ ! -x ./kanban ]; then
echo "[smoke] building kanban binary..."
(cd backend && CGO_ENABLED=1 go build -tags fts5 -o ../kanban .)
fi
# Boot.
./kanban --port "$PORT" --db "$DB" --initial-admin admin:adminpw \
> /tmp/kanban_files_smoke.log 2>&1 &
echo $! > "$PID_FILE"
# Wait for /api/board.
for _ in $(seq 1 30); do
if curl -sf -o /dev/null "$BASE/api/board"; then break; fi
sleep 0.2
done
# Login.
curl -sf -c "$COOKIE" -X POST "$BASE/api/auth/login" \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"adminpw"}' > /dev/null
# Column + card.
COL=$(curl -sf -b "$COOKIE" -X POST "$BASE/api/columns" \
-H 'Content-Type: application/json' \
-d '{"name":"To Do"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
CARD=$(curl -sf -b "$COOKIE" -X POST "$BASE/api/cards" \
-H 'Content-Type: application/json' \
-d "{\"column_id\":\"$COL\",\"title\":\"smoke\",\"requester\":\"r\"}" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
# Minimal PNG.
printf '\x89PNG\r\n\x1a\n' > "$PNG"
# Upload.
UP=$(curl -sf -b "$COOKIE" -X POST "$BASE/api/cards/$CARD/files" \
-F "file=@$PNG;type=image/png")
FID=$(echo "$UP" | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
[ -n "$FID" ] || { echo "[smoke] upload missing id"; exit 1; }
# List active.
N=$(curl -sf -b "$COOKIE" "$BASE/api/cards/$CARD/files" | python3 -c 'import sys,json;print(len(json.load(sys.stdin)))')
[ "$N" = "1" ] || { echo "[smoke] expected 1 file, got $N"; exit 1; }
# Serve.
CT=$(curl -sf -b "$COOKIE" -I "$BASE/api/files/$FID" | awk '/^[Cc]ontent-[Tt]ype/ {print $2}' | tr -d '\r\n')
echo "$CT" | grep -q image/png || { echo "[smoke] wrong content-type: $CT"; exit 1; }
# Delete.
HTTP=$(curl -sb "$COOKIE" -X DELETE -o /dev/null -w "%{http_code}" "$BASE/api/files/$FID")
[ "$HTTP" = "204" ] || { echo "[smoke] expected 204 on delete, got $HTTP"; exit 1; }
# List after delete.
N=$(curl -sf -b "$COOKIE" "$BASE/api/cards/$CARD/files" | python3 -c 'import sys,json;print(len(json.load(sys.stdin)))')
[ "$N" = "0" ] || { echo "[smoke] expected 0 after delete, got $N"; exit 1; }
echo "[smoke] OK"