Files
feadulta/tests/integration/test_subir_audio_api.sh
T

75 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Integración local para POST /wp-json/fea/v1/subir-audio (#222).
# Requiere FEA_TEST_URL, FEA_TEST_AUTH y FEA_TEST_POST_ID (post temporal).
set -euo pipefail
: "${FEA_TEST_URL:?Falta FEA_TEST_URL}"
: "${FEA_TEST_AUTH:?Falta FEA_TEST_AUTH}"
: "${FEA_TEST_POST_ID:?Falta FEA_TEST_POST_ID}"
endpoint="${FEA_TEST_URL%/}/wp-json/fea/v1/subir-audio"
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
# MP3 pequeño y válido (silencio MPEG-1 Layer III), sin depender de ffmpeg.
printf '\377\373\220\144' > "$tmpdir/audio.mp3"
dd if=/dev/zero bs=1 count=413 >> "$tmpdir/audio.mp3" 2>/dev/null
printf 'no es un mp3' > "$tmpdir/not-audio.txt"
# Un byte por encima del límite de aplicación de 25 MiB. Se comprueba antes
# del tipo de fichero, por lo que puede ser disperso y no necesita ser audio.
truncate -s 26214401 "$tmpdir/too-large.mp3"
assert_status() {
local expected="$1" actual="$2" label="$3" response_file="$4"
if [[ "$actual" != "$expected" ]]; then
echo "FAIL: $label — esperado HTTP $expected, recibido $actual" >&2
cat "$response_file" >&2 || true
exit 1
fi
}
status="$(curl -sS -o "$tmpdir/unauth.json" -w '%{http_code}' -X POST "$endpoint")"
assert_status 401 "$status" 'llamada sin autenticar' "$tmpdir/unauth.json"
status="$(curl -sS -o "$tmpdir/no-post.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -X POST "$endpoint")"
assert_status 400 "$status" 'falta post_id' "$tmpdir/no-post.json"
status="$(curl -sS -o "$tmpdir/no-audio.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "post_id=$FEA_TEST_POST_ID" "$endpoint")"
assert_status 400 "$status" 'falta audio' "$tmpdir/no-audio.json"
status="$(curl -sS -o "$tmpdir/too-large.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "post_id=$FEA_TEST_POST_ID" -F "audio=@$tmpdir/too-large.mp3;type=audio/mpeg" "$endpoint")"
assert_status 400 "$status" 'audio por encima de 25 MiB' "$tmpdir/too-large.json"
status="$(curl -sS -o "$tmpdir/wrong-type.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "post_id=$FEA_TEST_POST_ID" -F "audio=@$tmpdir/not-audio.txt;type=text/plain" "$endpoint")"
assert_status 400 "$status" 'extensión o mime no MP3' "$tmpdir/wrong-type.json"
status="$(curl -sS -o "$tmpdir/no-such-post.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F 'post_id=999999999' -F "audio=@$tmpdir/audio.mp3;type=audio/mpeg" "$endpoint")"
assert_status 404 "$status" 'post inexistente' "$tmpdir/no-such-post.json"
status="$(curl -sS -o "$tmpdir/success.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "post_id=$FEA_TEST_POST_ID" -F 'voice_id=NicoFeadulta2026' -F "audio=@$tmpdir/audio.mp3;type=audio/mpeg" "$endpoint")"
assert_status 201 "$status" 'subida válida' "$tmpdir/success.json"
python3 - "$tmpdir/success.json" "$FEA_TEST_POST_ID" "$tmpdir/audio.mp3" <<'PY'
import hashlib, json, sys
payload = json.load(open(sys.argv[1]))
assert int(payload['post_id']) == int(sys.argv[2]), payload
assert payload['audio_url'].endswith(f'/wp-content/uploads/tts/{sys.argv[2]}.mp3'), payload
assert payload['voice_id'] == 'NicoFeadulta2026', payload
assert payload['sha256'] == hashlib.sha256(open(sys.argv[3], 'rb').read()).hexdigest(), payload
assert 'previous_audio' in payload, payload
print('PASS: audio subido', payload['audio_url'])
PY
# La siguiente subida del mismo post debe exponer el estado anterior, para que
# el cliente pueda restaurarlo si su flujo posterior falla.
status="$(curl -sS -o "$tmpdir/replaced.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "post_id=$FEA_TEST_POST_ID" -F 'voice_id=NicoFeadulta2026' -F "audio=@$tmpdir/audio.mp3;type=audio/mpeg" "$endpoint")"
assert_status 201 "$status" 'reemplazo de audio' "$tmpdir/replaced.json"
python3 - "$tmpdir/replaced.json" "$FEA_TEST_POST_ID" <<'PY'
import json, sys
payload = json.load(open(sys.argv[1]))
assert payload['previous_audio']['url'].endswith(f'/wp-content/uploads/tts/{sys.argv[2]}.mp3'), payload
assert payload['previous_audio']['done'] == '1', payload
print('PASS: estado anterior devuelto')
PY