feat(api): endpoint para subir avatar de autor (#175)
This commit is contained in:
Executable
+90
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env bash
|
||||
# Integración local para POST /wp-json/fea/v1/subir-avatar (#175).
|
||||
# Requiere:
|
||||
# FEA_TEST_URL=http://localhost:8081
|
||||
# FEA_TEST_AUTH='usuario:application-password'
|
||||
# FEA_TEST_USER_ID=<usuario temporal existente>
|
||||
set -euo pipefail
|
||||
|
||||
: "${FEA_TEST_URL:?Falta FEA_TEST_URL}"
|
||||
: "${FEA_TEST_AUTH:?Falta FEA_TEST_AUTH}"
|
||||
: "${FEA_TEST_USER_ID:?Falta FEA_TEST_USER_ID}"
|
||||
|
||||
endpoint="${FEA_TEST_URL%/}/wp-json/fea/v1/subir-avatar"
|
||||
tmpdir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
# PNG RGB válido de 640×640, generado sin dependencias externas.
|
||||
python3 - "$tmpdir/avatar.png" <<'PY'
|
||||
import struct, sys, zlib
|
||||
width = height = 640
|
||||
raw = b''.join(b'\x00' + bytes((35, 100, 180)) * width for _ in range(height))
|
||||
def chunk(kind, data):
|
||||
return struct.pack('>I', len(data)) + kind + data + struct.pack('>I', zlib.crc32(kind + data) & 0xffffffff)
|
||||
png = b'\x89PNG\r\n\x1a\n'
|
||||
png += chunk(b'IHDR', struct.pack('>IIBBBBB', width, height, 8, 2, 0, 0, 0))
|
||||
png += chunk(b'IDAT', zlib.compress(raw, 9))
|
||||
png += chunk(b'IEND', b'')
|
||||
open(sys.argv[1], 'wb').write(png)
|
||||
PY
|
||||
|
||||
# PNG válido pero con una dimensión que excede el máximo permitido; queda muy
|
||||
# comprimido a propósito para cubrir la defensa contra image bombs.
|
||||
python3 - "$tmpdir/too-wide.png" <<'PY'
|
||||
import struct, sys, zlib
|
||||
width, height = 4097, 512
|
||||
raw = b''.join(b'\x00' + bytes((35, 100, 180)) * width for _ in range(height))
|
||||
def chunk(kind, data):
|
||||
return struct.pack('>I', len(data)) + kind + data + struct.pack('>I', zlib.crc32(kind + data) & 0xffffffff)
|
||||
png = b'\x89PNG\r\n\x1a\n'
|
||||
png += chunk(b'IHDR', struct.pack('>IIBBBBB', width, height, 8, 2, 0, 0, 0))
|
||||
png += chunk(b'IDAT', zlib.compress(raw, 9))
|
||||
png += chunk(b'IEND', b'')
|
||||
open(sys.argv[1], 'wb').write(png)
|
||||
PY
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# La ruta existe y no permite una llamada sin autenticar.
|
||||
status="$(curl -sS -o "$tmpdir/unauth.json" -w '%{http_code}' -X POST "$endpoint")"
|
||||
assert_status 401 "$status" 'llamada sin autenticar' "$tmpdir/unauth.json"
|
||||
|
||||
# Autenticada, pero sin destino: no puede persistir nada.
|
||||
status="$(curl -sS -o "$tmpdir/no-user.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -X POST "$endpoint")"
|
||||
assert_status 400 "$status" 'falta user_id' "$tmpdir/no-user.json"
|
||||
|
||||
# Un usuario válido sin imagen no puede crear attachments vacíos.
|
||||
status="$(curl -sS -o "$tmpdir/no-avatar.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "user_id=$FEA_TEST_USER_ID" "$endpoint")"
|
||||
assert_status 400 "$status" 'falta avatar' "$tmpdir/no-avatar.json"
|
||||
|
||||
# Una imagen-bomba comprimida se rechaza por dimensiones antes de abrir el editor.
|
||||
status="$(curl -sS -o "$tmpdir/too-wide.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "user_id=$FEA_TEST_USER_ID" -F "avatar=@$tmpdir/too-wide.png;type=image/png" "$endpoint")"
|
||||
assert_status 400 "$status" 'dimensiones excesivas' "$tmpdir/too-wide.json"
|
||||
|
||||
# Usuario inexistente: no puede crear attachments huérfanos.
|
||||
status="$(curl -sS -o "$tmpdir/no-such-user.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F 'user_id=999999999' -F "avatar=@$tmpdir/avatar.png;type=image/png" "$endpoint")"
|
||||
assert_status 404 "$status" 'usuario inexistente' "$tmpdir/no-such-user.json"
|
||||
|
||||
# Camino feliz: el endpoint crea attachment y devuelve el avatar asignado.
|
||||
status="$(curl -sS -o "$tmpdir/success.json" -w '%{http_code}' -u "$FEA_TEST_AUTH" -F "user_id=$FEA_TEST_USER_ID" -F "avatar=@$tmpdir/avatar.png;type=image/png" "$endpoint")"
|
||||
assert_status 201 "$status" 'subida válida' "$tmpdir/success.json"
|
||||
|
||||
python3 - "$tmpdir/success.json" "$FEA_TEST_USER_ID" <<'PY'
|
||||
import json, os, sys
|
||||
payload = json.load(open(sys.argv[1]))
|
||||
assert int(payload['user_id']) == int(sys.argv[2]), payload
|
||||
assert int(payload['attachment_id']) > 0, payload
|
||||
assert payload['avatar_url'].startswith(('http://', 'https://')), payload
|
||||
assert payload['width'] == 512 and payload['height'] == 512, payload
|
||||
previous = os.environ.get('FEA_TEST_PREVIOUS_ATTACHMENT_ID')
|
||||
if previous:
|
||||
assert int(payload['previous_attachment_id']) == int(previous), payload
|
||||
print('PASS: avatar asignado', payload['attachment_id'])
|
||||
PY
|
||||
Reference in New Issue
Block a user