Pedido de Leo (27-oct): mover un pendiente a otra columna sin arrastrar y bajar a la vez, cambiar la columna desde el detalle, y un solo campeón por pendiente que es quien lo mueve. - backend/app.py: campo «campeon» (uno de los responsables; por omisión el primero). PATCH /api/tarea y POST /api/tareas/orden solo cambian la columna o el campeón si quien escribe es el campeón, un administrador o TAREAS_MUEVEN_SIEMPRE (claude, por los lotes). GET /api/tareas trae campeon y mueven_siempre. - kanban.js / tablero.css: avatar del campeón primero y con anillo; flechas ← → en la tarjeta; franja fija arriba con las 4 columnas mientras se arrastra; botones de Columna y selector de Campeón en el detalle; tarjetas de otros sin arrastre ni flechas. - tablero.py y lotes/README.md: «campeon» se puede poner en un lote. - tests-campeon.sh (25 pruebas); tests-1014.sh: el PATCH de bob ya no cambia la columna. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013SfRSvyewSyFLfK9mjbGL8
61 lines
5.4 KiB
Bash
61 lines
5.4 KiB
Bash
#!/usr/bin/env bash
|
|
# Pruebas del 27-oct (Leo): campeón de cada pendiente — solo él, los administradores y TAREAS_MUEVEN_SIEMPRE (claude)
|
|
# lo cambian de columna o le pasan el campeón a otra persona. Arranca app.py con datos temporales; no toca el servidor.
|
|
# Uso: bash backend/tests-campeon.sh <ruta-a-hbox-docs> [puerto]
|
|
set -u
|
|
REPO=${1:?ruta a hbox-docs}; PORT=${2:-8098}
|
|
T=$(mktemp -d); export ACTAS_DIR=$T/actas HTPASSWD_FILE=$T/htpasswd HTPASSWD_LOCK=$T/.lock ACTAS_ADMINS=leo PORT
|
|
mkdir -p $ACTAS_DIR $T/equipo $T/tareas; : > $T/htpasswd
|
|
for u in leo adriana jesus michelle claude; do
|
|
echo "{\"id\":\"$u\",\"nombre\":\"$u\",\"area\":\"ingenieria\",\"activo\":true}" > $T/equipo/$u.json
|
|
done
|
|
# t-a: de antes (sin campo campeon): el campeón es el primero, adriana
|
|
echo '{"id":"t-a","titulo":"Cotizar gabinetes","responsable":"adriana, jesus","estado":"por-hacer","pista":"compras","sitios":["qro"],"orden":0,"historial":[]}' > $T/tareas/t-a.json
|
|
echo '{"id":"t-b","titulo":"Solo de Jesús","responsable":"jesus","estado":"por-hacer","pista":"compras","sitios":["qro"],"orden":1,"historial":[]}' > $T/tareas/t-b.json
|
|
echo '{"id":"t-c","titulo":"Texto libre","responsable":"Proveedor X","estado":"por-hacer","pista":"compras","sitios":["qro"],"orden":2,"historial":[]}' > $T/tareas/t-c.json
|
|
python3 $REPO/backend/app.py > $T/app.log 2>&1 &
|
|
APP=$!; trap "kill $APP 2>/dev/null" EXIT; sleep 1.8
|
|
U="http://127.0.0.1:$PORT"
|
|
ok=0; fail=0
|
|
check() { if [[ "$3" == *"$2"* ]]; then ok=$((ok+1)); echo " ✓ $1"; else fail=$((fail+1)); echo " ✕ $1 — esperaba «$2», obtuve: ${3:0:220}"; fi; }
|
|
as() { curl -s -H "X-Remote-User: $1" -H "Content-Type: application/json" "${@:2}"; }
|
|
campo() { python3 -c "import json,sys; d=json.load(sys.stdin); t=[x for x in d['tareas'] if x['id']=='$1'][0]; print(t.get('$2'))"; }
|
|
|
|
echo "## campeón por omisión"
|
|
check "pendiente viejo: el primero de la lista" "adriana" "$(as leo $U/api/tareas | campo t-a campeon)"
|
|
check "GET /api/tareas trae mueven_siempre" '"mueven_siempre":["claude","leo"]' "$(as leo $U/api/tareas)"
|
|
check "alta: campeón = primer responsable" '"campeon":"michelle"' "$(as leo -X POST -d '{"id":"t-n","titulo":"Nuevo","responsable":"michelle, jesus","pista":"ingenieria"}' $U/api/tareas)"
|
|
check "alta con campeón elegido" '"campeon":"jesus"' "$(as leo -X POST -d '{"id":"t-n2","titulo":"Nuevo 2","responsable":"michelle, jesus","campeon":"jesus","pista":"ingenieria"}' $U/api/tareas)"
|
|
check "campeón que no es responsable: error" "tiene que ser uno de los responsables" "$(as leo -X POST -d '{"id":"t-n3","titulo":"Nuevo 3","responsable":"michelle","campeon":"jesus","pista":"ingenieria"}' $U/api/tareas)"
|
|
|
|
echo "## quién mueve"
|
|
check "otro responsable (jesus) no mueve t-a" "Solo adriana, campe" "$(as jesus -X PATCH -d '{"estado":"en-curso"}' "$U/api/tarea?id=t-a")"
|
|
check "…y el pendiente no cambió" "por-hacer" "$(as leo $U/api/tareas | campo t-a estado)"
|
|
check "el campeón (adriana) sí mueve" '"estado":"en-curso"' "$(as adriana -X PATCH -d '{"estado":"en-curso"}' "$U/api/tarea?id=t-a")"
|
|
check "un administrador (leo) sí mueve" '"estado":"bloqueado"' "$(as leo -X PATCH -d '{"estado":"bloqueado"}' "$U/api/tarea?id=t-a")"
|
|
check "claude (lotes) sí mueve" '"estado":"en-curso"' "$(as claude -X PATCH -d '{"estado":"en-curso","_nota":"lote"}' "$U/api/tarea?id=t-a")"
|
|
check "alguien que no es responsable no mueve t-b" "403" "$(as michelle -o /dev/null -w '%{http_code}' -X PATCH -d '{"estado":"hecho"}' "$U/api/tarea?id=t-b")"
|
|
check "sin campeón (solo texto libre) cualquiera mueve" '"estado":"en-curso"' "$(as michelle -X PATCH -d '{"estado":"en-curso"}' "$U/api/tarea?id=t-c")"
|
|
check "los demás campos sí los edita otro responsable" '"fecha_limite":"2026-11-05"' "$(as jesus -X PATCH -d '{"fecha_limite":"2026-11-05"}' "$U/api/tarea?id=t-a")"
|
|
|
|
echo "## pasar el campeón"
|
|
check "otro responsable no se puede quedar el campeón" "puede cambiar el campe" "$(as jesus -X PATCH -d '{"campeon":"jesus"}' "$U/api/tarea?id=t-a")"
|
|
check "quitar al campeón de los responsables tampoco" "puede cambiar el campe" "$(as jesus -X PATCH -d '{"responsable":"jesus"}' "$U/api/tarea?id=t-a")"
|
|
check "agregar a alguien sin tocar al campeón sí" '"campeon":"adriana"' "$(as jesus -X PATCH -d '{"responsable":"adriana, jesus, michelle"}' "$U/api/tarea?id=t-a")"
|
|
check "el campeón lo pasa a jesus" '"campeon":"jesus"' "$(as adriana -X PATCH -d '{"campeon":"jesus"}' "$U/api/tarea?id=t-a")"
|
|
check "queda en el historial" "campeon: adriana → jesus" "$(cat $T/tareas/t-a.json)"
|
|
check "ahora adriana ya no mueve" "Solo jesus, campe" "$(as adriana -X PATCH -d '{"estado":"hecho"}' "$U/api/tarea?id=t-a")"
|
|
check "y jesus sí" '"estado":"hecho"' "$(as jesus -X PATCH -d '{"estado":"hecho"}' "$U/api/tarea?id=t-a")"
|
|
check "si el campeón sale de los responsables (admin), pasa al primero" '"campeon":"michelle"' "$(as leo -X PATCH -d '{"responsable":"michelle, adriana"}' "$U/api/tarea?id=t-a")"
|
|
|
|
echo "## orden de columna (arrastre)"
|
|
r=$(as adriana -X POST -d '{"estado":"hecho","ids":["t-b","t-c"]}' $U/api/tareas/orden)
|
|
check "orden: a t-b (de jesus) no lo cambia de columna" '"negados":["t-b"]' "$r"
|
|
check "…t-b sigue en por-hacer" "por-hacer" "$(as leo $U/api/tareas | campo t-b estado)"
|
|
check "…t-c (sin campeón) sí pasó" "hecho" "$(as leo $U/api/tareas | campo t-c estado)"
|
|
|
|
echo "## lotes"
|
|
check "tablero.py acepta «campeon» en poner" "campeon" "$(grep -o '"campeon"' $REPO/backend/tablero.py | head -1)"
|
|
|
|
echo; echo "Resultado: $ok bien, $fail mal"; [ $fail -eq 0 ]
|