|
|
|
@@ -244,9 +244,12 @@ reubicó su contenedor según el breakpoint.
|
|
|
|
|
## Consecuencias
|
|
|
|
|
|
|
|
|
|
- Checkout real de punta a punta (pago + envío calculado) queda
|
|
|
|
|
desplegado y verificado a nivel API/backend, pero **ambos proveedores
|
|
|
|
|
siguen en modo sandbox** — no se ha completado ni un pago real ni un
|
|
|
|
|
envío real todavía. Ver checklist de pruebas abajo.
|
|
|
|
|
desplegado y verificado con navegador real hasta la redirección al
|
|
|
|
|
banco de PSE (ver nota de implementación 2026-09-10 abajo), pero
|
|
|
|
|
**ambos proveedores siguen en modo sandbox** — no se ha completado ni
|
|
|
|
|
un pago real ni un envío real todavía, y el login bancario de PSE
|
|
|
|
|
tampoco se completó (falta credencial de prueba). Ver checklist
|
|
|
|
|
ampliado abajo.
|
|
|
|
|
- La precisión de la tarifa de envío depende de cargar peso/dimensiones
|
|
|
|
|
reales por producto — deuda de datos explícita, no de código; candidato
|
|
|
|
|
natural a extender el importador CSV existente con columnas nuevas.
|
|
|
|
@@ -262,37 +265,163 @@ reubicó su contenedor según el breakpoint.
|
|
|
|
|
|
|
|
|
|
## Checklist de pruebas reales desde el storefront (pendiente, no ejecutado en este ADR)
|
|
|
|
|
|
|
|
|
|
Todo lo de arriba se verificó a nivel API/backend con llamadas directas
|
|
|
|
|
o carritos de prueba armados por API — **no** todavía manejando el
|
|
|
|
|
storefront real como lo haría un comprador. Pendiente, con la próxima
|
|
|
|
|
sesión que tenga acceso a un navegador real:
|
|
|
|
|
Todo lo de arriba se verificó primero a nivel API/backend con llamadas
|
|
|
|
|
directas o carritos de prueba armados por API, sin manejar el
|
|
|
|
|
storefront real como lo haría un comprador. Esa parte del checklist se
|
|
|
|
|
cerró el 2026-09-10 (ver nota de implementación abajo) usando un
|
|
|
|
|
navegador real de verdad, no curl.
|
|
|
|
|
|
|
|
|
|
1. **Pago PSE completo:** agregar un producto real al carrito → checkout
|
|
|
|
|
→ elegir PSE → seleccionar un banco del listado real (sandbox) →
|
|
|
|
|
confirmar que la redirección al banco ocurre (esto es justo lo que
|
|
|
|
|
nunca se probó — el nombre del campo de URL de `bank.create()` está
|
|
|
|
|
manejado a la defensiva y podría no matchear ningún candidato) →
|
|
|
|
|
volver a `/checkout/pse/return` → confirmar que la orden queda en
|
|
|
|
|
estado correcto.
|
|
|
|
|
2. **Envío calculado real:** en el paso de dirección del checkout,
|
|
|
|
|
confirmar que el precio de envío mostrado ya no es el fijo de
|
|
|
|
|
$15.000 sino el que devuelve EnvíoClick en vivo para esa dirección
|
|
|
|
|
(visible también sin completar el pago, solo llegando al paso de
|
|
|
|
|
shipping).
|
|
|
|
|
3. **Resiliencia del fallback de envío:** si es posible, forzar una
|
|
|
|
|
dirección o producto que haga fallar la cotización real (por ejemplo,
|
|
|
|
|
un DANE code inválido) y confirmar que el checkout sigue avanzando
|
|
|
|
|
con el precio de respaldo en vez de romperse — el comportamiento
|
|
|
|
|
documentado en `calculatePrice()`, nunca ejercitado con un fallo real.
|
|
|
|
|
4. **Banner dinámico:** confirmar en `/` que el carrusel muestra
|
|
|
|
|
productos reales del catálogo (no las tres imágenes viejas
|
|
|
|
|
hardcodeadas) y que cada slide lleva al producto correcto al hacer
|
|
|
|
|
clic.
|
|
|
|
|
5. **Buscador:** en un viewport mobile real (no solo devtools), confirmar
|
|
|
|
|
que el buscador ya no se ve recortado y que el autocompletado
|
|
|
|
|
despliega bien debajo de la fila nueva a todo el ancho.
|
|
|
|
|
6. **Webhook de ePayco con un pago real de sandbox:** confirmar que,
|
|
|
|
|
tras completar un pago PSE de prueba desde el banco sandbox, el
|
|
|
|
|
webhook mueve la orden a completada sin intervención manual (hoy solo
|
|
|
|
|
se confirmó que el endpoint responde `200` a un `POST` sintético, no
|
|
|
|
|
con un webhook real disparado por ePayco).
|
|
|
|
|
### RESUELTO (2026-09-10) — navegador real vía Docker en la NAS
|
|
|
|
|
|
|
|
|
|
El shell donde corren los comandos de esta sesión tiene su propia red
|
|
|
|
|
restringida para `npm` (un proxy interno que rompe algunas descargas de
|
|
|
|
|
paquetes — no relacionado con la red real del lab). **Docker en la NAS
|
|
|
|
|
sí sale a internet real, sin ese filtro** — confirmado en vivo
|
|
|
|
|
(`docker pull` normal, un contenedor de Node golpeando
|
|
|
|
|
`registry.npmjs.org` sin problema). Se armó un harness reutilizable con
|
|
|
|
|
la imagen oficial `mcr.microsoft.com/playwright:v1.51.1-jammy`
|
|
|
|
|
(Chromium real) corrida puntualmente contra `shop.cruzcloud.net`,
|
|
|
|
|
guardado en `.browser-scratch/` en la raíz del lab (`checks.mjs` +
|
|
|
|
|
`README.md` con el comando exacto para reactivarlo — no hace falta
|
|
|
|
|
ningún contenedor corriendo de forma persistente, la imagen y las
|
|
|
|
|
dependencias ya quedan cacheadas localmente en la NAS).
|
|
|
|
|
|
|
|
|
|
**Hallazgo no obvio:** el daemon de Docker de la NAS ve un filesystem
|
|
|
|
|
distinto al que ve el shell de esta sesión (que corre en su propio
|
|
|
|
|
sandbox, aunque monte los mismos repos git) — un volumen `-v` apuntando
|
|
|
|
|
a un path de `/tmp` del shell no tira error pero monta un directorio
|
|
|
|
|
vacío del lado del contenedor. Hay que usar un path bajo
|
|
|
|
|
`/media/HDD-Storage/AppData/k3d-lab-v3/lab-cruzcloud/` (montaje real
|
|
|
|
|
compartido) para que el contenedor vea los archivos de verdad.
|
|
|
|
|
|
|
|
|
|
**Resultados, con capturas reales:**
|
|
|
|
|
|
|
|
|
|
1. **Pago PSE completo — FUNCIONA.** Carrito → dirección Bogotá →
|
|
|
|
|
envío calculado → banco PSE (sandbox) → **la redirección real
|
|
|
|
|
funcionó**: el nombre de campo manejado a la defensiva en
|
|
|
|
|
`bank.create()`/`initiatePayment` matcheó al primer intento, y el
|
|
|
|
|
navegador llegó a la página real de autorización de PSE
|
|
|
|
|
(`registro.desarrollo.pse.com.co`, ambiente de desarrollo/sandbox
|
|
|
|
|
de PSE Colombia). No se completó el login bancario (requiere
|
|
|
|
|
credenciales de prueba específicas de PSE que no se tenían a mano) —
|
|
|
|
|
sigue pendiente confirmar el webhook con un pago sandbox completado
|
|
|
|
|
de principio a fin (ver checklist nuevo abajo).
|
|
|
|
|
2. **Envío calculado real — FUNCIONA.** El paso de pago mostró
|
|
|
|
|
`Envío $8.941` (mismo valor ya visto en la verificación por API de
|
|
|
|
|
la sección anterior) en vez del fijo de $15.000, para una dirección
|
|
|
|
|
real de Bogotá.
|
|
|
|
|
3. **Banner dinámico — funciona, pero destapó un bug real:** un
|
|
|
|
|
producto marcado `featured: true` pero **sin stock**
|
|
|
|
|
(`available: false`, "Toy Story 5 - Rex") salía primero en el
|
|
|
|
|
carrusel con botón "Comprar ahora" hacia una página donde en
|
|
|
|
|
realidad no se puede comprar. Corregido en el mismo commit que este
|
|
|
|
|
hallazgo (filtro adicional `&& product.available` en
|
|
|
|
|
`app/page.tsx`).
|
|
|
|
|
4. **Buscador mobile — funciona.** El buscador ya no se ve recortado,
|
|
|
|
|
y el autocompletado despliega bien debajo de la fila nueva a todo el
|
|
|
|
|
ancho (probado con el viewport de un iPhone 13 real, no devtools).
|
|
|
|
|
5. **Bug adicional encontrado, no buscado:** el sandbox real de ePayco
|
|
|
|
|
(`bank.getBanks()`) devuelve un primer elemento placeholder
|
|
|
|
|
(`bankCode: "0"`, `"A continuación seleccione su banco..."` con el
|
|
|
|
|
texto mal decodificado — unicode escapado literal) mezclado con los
|
|
|
|
|
bancos reales, mostrado como una opción más, seleccionable, en el
|
|
|
|
|
`<select>` del checkout. Ningún banco PSE real tiene código "0" —
|
|
|
|
|
se filtra explícitamente en `pse-banks/route.ts`.
|
|
|
|
|
|
|
|
|
|
Ampliado 2026-09-10 con el resto de la superficie real del storefront
|
|
|
|
|
(4 páginas + `components/{account,cart,catalog,checkout,home,layout,
|
|
|
|
|
product,search,wishlist}`), agrupado por riesgo, y ejecutado el mismo
|
|
|
|
|
día contra `shop.cruzcloud.net` con el harness de `.browser-scratch/`.
|
|
|
|
|
|
|
|
|
|
### RESUELTO (2026-09-11) — segunda tanda con navegador real
|
|
|
|
|
|
|
|
|
|
Resultados reales, uno por uno (código de cada prueba en
|
|
|
|
|
`checks.mjs`):
|
|
|
|
|
|
|
|
|
|
- **`/checkout` con carrito vacío (ítem 9) — OK.** Muestra "Tu carrito
|
|
|
|
|
está vacío" con link a `/catalog`, no rompe.
|
|
|
|
|
- **Fallback "Confirmar por WhatsApp" (ítem 10) — OK.** Abre
|
|
|
|
|
`api.whatsapp.com/send?phone=...` en pestaña nueva con el mensaje del
|
|
|
|
|
pedido armado correctamente.
|
|
|
|
|
- **Filtros de `/catalog` (ítem 11) — OK.** Un filtro de categoría real
|
|
|
|
|
("Figuras de acción") redujo los productos mostrados de 18 a 4. Nota:
|
|
|
|
|
estos filtros (categoría/marca/edad dentro de la barra lateral) son
|
|
|
|
|
**estado de cliente, no reflejado en la URL** — distinto de los
|
|
|
|
|
filtros por query param (`?category=...`) que sí usa la navegación
|
|
|
|
|
del header. Ninguno de los dos es un bug, son dos mecanismos
|
|
|
|
|
distintos coexistiendo; queda como nota para no confundirlos.
|
|
|
|
|
- **Búsqueda sin resultados (ítem 12) — BUG real encontrado y
|
|
|
|
|
corregido.** El dropdown de autocompletado no mostraba absolutamente
|
|
|
|
|
nada (ni "Buscando…" ni ningún mensaje) cuando una búsqueda de 2+
|
|
|
|
|
caracteres no tenía coincidencias — el usuario se quedaba sin
|
|
|
|
|
feedback de que su búsqueda había corrido. Corregido en
|
|
|
|
|
`predictive-search.tsx`: ahora muestra "No encontramos resultados
|
|
|
|
|
para…" con el botón de buscar en todo el catálogo.
|
|
|
|
|
- **Slug de producto inválido (ítem 14) — hallazgo, no corregido
|
|
|
|
|
todavía.** La página sí muestra el contenido correcto de "Este tesoro
|
|
|
|
|
no existe" (el código ya llama a `notFound()` de
|
|
|
|
|
`next/navigation`, como corresponde), **pero la respuesta HTTP real
|
|
|
|
|
es `200`, no `404`** — confirmado independientemente con `curl`, no
|
|
|
|
|
es un artefacto de Playwright. No se investigó a fondo en qué capa se
|
|
|
|
|
pierde el status real (Next.js standalone vs. alguna capa de
|
|
|
|
|
Cloudflare/NPM/Traefik en el medio, ver
|
|
|
|
|
`incidente-cloudflared-504-quic-2026-08.md` para precedente de
|
|
|
|
|
problemas de red en esa cadena) — bajo impacto en la experiencia del
|
|
|
|
|
usuario (el contenido es correcto), pero sí afecta SEO/crawlers.
|
|
|
|
|
Queda como pendiente de investigar, no de corregir a ciegas.
|
|
|
|
|
- **Zoom interactivo del producto (ítem 15) — OK.** Hover-zoom y el
|
|
|
|
|
modal de click-to-zoom siguen funcionando igual tras los cambios
|
|
|
|
|
recientes al storefront.
|
|
|
|
|
- **Wishlist/favoritos (ítem 17) — OK.** Agregar a favoritos +
|
|
|
|
|
recargar la página: persiste correctamente vía `localStorage`.
|
|
|
|
|
- **Otros viewports, tablet y desktop grande (ítem 19) — OK.**
|
|
|
|
|
Capturas guardadas, sin problemas de layout visibles en el banner ni
|
|
|
|
|
el header en esos anchos.
|
|
|
|
|
- **Página 404 genérica (ítem 20) — OK.** Una ruta que no existe cae en
|
|
|
|
|
`not-found.tsx` con status HTTP `404` real (a diferencia del caso de
|
|
|
|
|
producto inválido arriba — la diferencia de comportamiento entre
|
|
|
|
|
ambos casos es justamente lo que quedó como pendiente de investigar).
|
|
|
|
|
- **Accesibilidad básica (ítem 21) — OK, parcial.** El buscador es
|
|
|
|
|
alcanzable navegando solo con `Tab` desde el body, sin mouse. Falta
|
|
|
|
|
probar el resto del flujo de checkout por teclado.
|
|
|
|
|
- **Registro/login con email y contraseña (parte del ítem 16) — OK.**
|
|
|
|
|
Crear cuenta con nombre/apellido/email/contraseña funciona y deja la
|
|
|
|
|
sesión iniciada. La parte de Google OAuth sigue sin probarse (necesita
|
|
|
|
|
una cuenta de Google real, no algo que se pueda automatizar sin
|
|
|
|
|
credenciales).
|
|
|
|
|
|
|
|
|
|
### Pendiente — lo que queda sin probar
|
|
|
|
|
|
|
|
|
|
3. **Resiliencia del fallback de envío:** forzar una dirección o
|
|
|
|
|
producto que haga fallar la cotización real de EnvíoClick (ej. un
|
|
|
|
|
DANE code inválido) y confirmar que el checkout sigue avanzando con
|
|
|
|
|
el precio de respaldo ($15.000) en vez de romperse — comportamiento
|
|
|
|
|
documentado en `calculatePrice()`, nunca ejercitado con un fallo
|
|
|
|
|
real.
|
|
|
|
|
6. **Webhook de ePayco con un pago real de sandbox completado:**
|
|
|
|
|
conseguir credenciales de prueba reales de PSE (persona/clave de
|
|
|
|
|
algún banco del ambiente `desarrollo`), completar el login bancario
|
|
|
|
|
de punta a punta, y confirmar que el webhook mueve la orden a
|
|
|
|
|
completada sin intervención manual.
|
|
|
|
|
7. **Pago cancelado o rechazado en el banco PSE:** confirmar que la
|
|
|
|
|
orden no queda en un estado ambiguo ("colgada" en
|
|
|
|
|
`pending_authorization` para siempre).
|
|
|
|
|
8. **Persona jurídica + NIT** en el formulario de PSE — solo se probó
|
|
|
|
|
persona natural con cédula.
|
|
|
|
|
13. **Selección de variantes** (cuando un producto tiene más de una) y
|
|
|
|
|
que el precio/disponibilidad mostrado cambie según la variante
|
|
|
|
|
elegida — ningún producto probado hasta ahora tenía más de una
|
|
|
|
|
variante real.
|
|
|
|
|
14b. **Investigar por qué `/product/<slug-inválido>` responde HTTP 200**
|
|
|
|
|
en vez de 404 pese a llamar `notFound()` correctamente (ver
|
|
|
|
|
hallazgo arriba) — identificar la capa responsable antes de tocar
|
|
|
|
|
código.
|
|
|
|
|
16b. **Login con Google (OAuth completo)** incluyendo
|
|
|
|
|
`/auth/google/callback` — necesita una cuenta de Google real de
|
|
|
|
|
prueba.
|
|
|
|
|
18. **Bug conocido de Firefox Android** (ver memoria de proyecto,
|
|
|
|
|
`known-bug-firefox-android-layout`) — Playwright puede emular
|
|
|
|
|
Android/Chrome pero no Firefox; hace falta `playwright-firefox` o
|
|
|
|
|
un dispositivo real.
|
|
|
|
|
21b. **Accesibilidad del checkout completo** por teclado (no solo el
|
|
|
|
|
buscador) — tab order y foco visible en los 3 pasos.
|