Compare commits

...
Author SHA1 Message Date
devopsandClaude Sonnet 5 8d44f2e771 fix(ecommerce): mostrar mensaje cuando el buscador no tiene resultados
Encontrado probando en vivo con navegador real (Docker + Playwright):
una búsqueda de 2+ caracteres sin coincidencias no mostraba nada -- ni
"Buscando…" ni ningún mensaje. El usuario quedaba sin feedback de que
su búsqueda de verdad corrió. Se agrega un estado vacío con el botón
de buscar en todo el catálogo (esa búsqueda completa puede usar
criterios más amplios que el autocompletado).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-11 13:08:50 +00:00
devopsandClaude Sonnet 5 352762b9d2 Merge: ampliar checklist de pruebas reales pendientes (ADR 0010)
Build and Push Docs Portal / Escaneo de Secretos (Gitleaks) (push) Successful in 20s
Build and Push Docs Portal / Construir y publicar Docs Portal (push) Successful in 6m6s
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-10 21:40:11 +00:00
devopsandClaude Sonnet 5 58cc93bb2f docs(adr-0010): ampliar checklist de pruebas reales pendientes
Cubre el resto de la superficie del storefront (checkout edge cases,
filtros de catalogo, variantes de producto, cuenta/wishlist,
accesibilidad, otros viewports) agrupado por riesgo, no solo lo ya
probado.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-10 21:40:09 +00:00
gitea-actions 5eaa94818f chore(gitops): deploy Docs Portal v1.0.241 [skip ci] 2026-09-10 17:56:48 +00:00
gitea-actions 66a81ad9a3 chore(gitops): deploy Medusa v1.0.239 [skip ci] 2026-09-10 17:49:42 +00:00
devops 39e1bf61d3 chore: release v1.0.240 [skip ci] 2026-09-10 17:23:09 +00:00
devopsandClaude Sonnet 5 b5a1f70d1d Merge: documentar resultados de pruebas con navegador real (ADR 0010)
Build and Push Docs Portal / Escaneo de Secretos (Gitleaks) (push) Successful in 38s
Build and Push Docs Portal / Construir y publicar Docs Portal (push) Successful in 6m20s
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-10 17:13:12 +00:00
devopsandClaude Sonnet 5 9d231322b8 docs(adr-0010): resultados de pruebas con navegador real + checklist ampliado
Cierra la mayor parte del checklist de pruebas reales que había quedado
pendiente: pago PSE hasta la redirección al banco, envío calculado
visible, banner y buscador mobile -- todo verificado con Chromium real
(Docker + Playwright en la NAS, ver .browser-scratch/README.md). Deja
documentados los 2 bugs reales que esa prueba encontró (ya corregidos
en otro commit) y un checklist ampliado para la próxima sesión.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-10 17:13:10 +00:00
5 changed files with 160 additions and 40 deletions

No files matched your search

@@ -244,9 +244,12 @@ reubicó su contenedor según el breakpoint.
## Consecuencias ## Consecuencias
- Checkout real de punta a punta (pago + envío calculado) queda - Checkout real de punta a punta (pago + envío calculado) queda
desplegado y verificado a nivel API/backend, pero **ambos proveedores desplegado y verificado con navegador real hasta la redirección al
siguen en modo sandbox** — no se ha completado ni un pago real ni un banco de PSE (ver nota de implementación 2026-09-10 abajo), pero
envío real todavía. Ver checklist de pruebas abajo. **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 - 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 reales por producto — deuda de datos explícita, no de código; candidato
natural a extender el importador CSV existente con columnas nuevas. natural a extender el importador CSV existente con columnas nuevas.
@@ -262,37 +265,142 @@ reubicó su contenedor según el breakpoint.
## Checklist de pruebas reales desde el storefront (pendiente, no ejecutado en este ADR) ## 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 Todo lo de arriba se verificó primero a nivel API/backend con llamadas
o carritos de prueba armados por API — **no** todavía manejando el directas o carritos de prueba armados por API, sin manejar el
storefront real como lo haría un comprador. Pendiente, con la próxima storefront real como lo haría un comprador. Esa parte del checklist se
sesión que tenga acceso a un navegador real: 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 ### RESUELTO (2026-09-10) — navegador real vía Docker en la NAS
→ elegir PSE → seleccionar un banco del listado real (sandbox) →
confirmar que la redirección al banco ocurre (esto es justo lo que El shell donde corren los comandos de esta sesión tiene su propia red
nunca se probó — el nombre del campo de URL de `bank.create()` está restringida para `npm` (un proxy interno que rompe algunas descargas de
manejado a la defensiva y podría no matchear ningún candidato) → paquetes — no relacionado con la red real del lab). **Docker en la NAS
volver a `/checkout/pse/return` → confirmar que la orden queda en sí sale a internet real, sin ese filtro** — confirmado en vivo
estado correcto. (`docker pull` normal, un contenedor de Node golpeando
2. **Envío calculado real:** en el paso de dirección del checkout, `registry.npmjs.org` sin problema). Se armó un harness reutilizable con
confirmar que el precio de envío mostrado ya no es el fijo de la imagen oficial `mcr.microsoft.com/playwright:v1.51.1-jammy`
$15.000 sino el que devuelve EnvíoClick en vivo para esa dirección (Chromium real) corrida puntualmente contra `shop.cruzcloud.net`,
(visible también sin completar el pago, solo llegando al paso de guardado en `.browser-scratch/` en la raíz del lab (`checks.mjs` +
shipping). `README.md` con el comando exacto para reactivarlo — no hace falta
3. **Resiliencia del fallback de envío:** si es posible, forzar una ningún contenedor corriendo de forma persistente, la imagen y las
dirección o producto que haga fallar la cotización real (por ejemplo, dependencias ya quedan cacheadas localmente en la NAS).
un DANE code inválido) y confirmar que el checkout sigue avanzando
con el precio de respaldo en vez de romperse — el comportamiento **Hallazgo no obvio:** el daemon de Docker de la NAS ve un filesystem
documentado en `calculatePrice()`, nunca ejercitado con un fallo real. distinto al que ve el shell de esta sesión (que corre en su propio
4. **Banner dinámico:** confirmar en `/` que el carrusel muestra sandbox, aunque monte los mismos repos git) — un volumen `-v` apuntando
productos reales del catálogo (no las tres imágenes viejas a un path de `/tmp` del shell no tira error pero monta un directorio
hardcodeadas) y que cada slide lleva al producto correcto al hacer vacío del lado del contenedor. Hay que usar un path bajo
clic. `/media/HDD-Storage/AppData/k3d-lab-v3/lab-cruzcloud/` (montaje real
5. **Buscador:** en un viewport mobile real (no solo devtools), confirmar compartido) para que el contenedor vea los archivos de verdad.
que el buscador ya no se ve recortado y que el autocompletado
despliega bien debajo de la fila nueva a todo el ancho. **Resultados, con capturas reales:**
6. **Webhook de ePayco con un pago real de sandbox:** confirmar que,
tras completar un pago PSE de prueba desde el banco sandbox, el 1. **Pago PSE completo — FUNCIONA.** Carrito → dirección Bogotá →
webhook mueve la orden a completada sin intervención manual (hoy solo envío calculado → banco PSE (sandbox) → **la redirección real
se confirmó que el endpoint responde `200` a un `POST` sintético, no funcionó**: el nombre de campo manejado a la defensiva en
con un webhook real disparado por ePayco). `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`.
### Pendiente — checklist ampliado para la próxima sesión con navegador
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 — hoy solo se confirmó que el
endpoint responde `200` a un `POST` sintético y que la redirección
al banco ocurre, no el ciclo completo con notificación real.
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:
**Checkout / pagos**
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) cuando el comprador cancela o
el banco rechaza — hoy solo se probó el camino feliz hasta la
redirección.
8. **Persona jurídica + NIT** en el formulario de PSE — solo se probó
persona natural con cédula.
9. **`/checkout` con carrito vacío** (acceso directo por URL, sin pasar
por un producto primero).
10. **Fallback "Confirmar por WhatsApp"** (visible cuando falla la
lista de bancos o como alternativa siempre disponible): que el link
arme el mensaje correcto con los datos del pedido.
**Catálogo y búsqueda**
11. **Filtros de `/catalog`** (categoría/colección/marca/precio — las
facetas de Meilisearch, ver ADR 0006) con navegador real: que
aplicar/combinar filtros actualice los resultados y la URL.
12. **Búsqueda sin resultados** — confirmar que muestra un mensaje
claro en vez de quedar vacío sin explicación.
**Producto**
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.
14. **Slug de producto inválido** → debe caer en `not-found.tsx`
(`app/not-found.tsx`), no en un error sin manejar.
15. **Zoom interactivo del producto** (hover + modal click-to-zoom,
`product-gallery.tsx`) — re-verificar con navegador real, la última
vez que se probó fue antes de esta tanda de cambios al storefront.
**Cuenta y wishlist**
16. **Login/registro de cliente real** (Google OAuth de punta a punta
incluyendo `/auth/google/callback`, y con contraseña) — nunca
ejercitado con un navegador real en ninguna sesión.
17. **Wishlist/favoritos** (`wishlist-drawer.tsx`): agregar/quitar y
confirmar que persiste entre recargas (guardado en `localStorage`,
por-viewer — no hay forma de verificarlo por API).
**Transversal**
18. **Bug conocido de Firefox Android** (ver memoria de proyecto,
`known-bug-firefox-android-layout`): el layout se corta/desplaza
solo en Firefox Android — Playwright puede emular Android/Chrome
pero no Firefox; si se necesita reproducir esto específicamente hace
falta `playwright-firefox` o un dispositivo real.
19. **Otros viewports** (tablet, desktop grande) para el banner y el
buscador — solo se probaron mobile (iPhone 13) y desktop 1280px.
20. **Página 404** (`app/not-found.tsx`) — nunca visitada con navegador
real.
21. **Accesibilidad básica**: navegación completa por teclado (tab
order, foco visible) en el checkout y el buscador — Playwright
puede simular esto (`page.keyboard`), no probado todavía.
@@ -25,7 +25,7 @@ spec:
runAsNonRoot: false runAsNonRoot: false
containers: containers:
- name: app - name: app
image: gitea.cruzcloud.net/devops/docs-portal:v1.0.237 image: gitea.cruzcloud.net/devops/docs-portal:v1.0.241
# El base saca TODAS las capabilities. Probado en vivo y # El base saca TODAS las capabilities. Probado en vivo y
# revertido: con drop: ALL (aunque se agregue NET_BIND_SERVICE # revertido: con drop: ALL (aunque se agregue NET_BIND_SERVICE
# de vuelta) el propio entrypoint de nginx:1.27-alpine falla al # de vuelta) el propio entrypoint de nginx:1.27-alpine falla al
@@ -65,7 +65,7 @@ spec:
memory: 64Mi memory: 64Mi
- name: migrations - name: migrations
image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.234 image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.239
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
command: command:
- node - node
@@ -86,7 +86,7 @@ spec:
containers: containers:
- name: app - name: app
image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.234 image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.239
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
envFrom: envFrom:
- configMapRef: - configMapRef:
@@ -87,6 +87,18 @@ export function PredictiveSearch() {
Buscando… Buscando…
</div> </div>
)} )}
{/* Encontrado probando en vivo con navegador real: sin este bloque,
una busqueda de 2+ caracteres sin coincidencias no mostraba nada
(ni "buscando" ni un mensaje) -- el usuario se quedaba sin ningun
feedback de que su busqueda de verdad corrio. Se ofrece igual el
boton de buscar en todo el catalogo porque esa busqueda completa
puede usar criterios mas amplios que el autocompletado. */}
{!loading && normalized.length >= 2 && matches.length === 0 && (
<div className="absolute left-0 right-0 top-[calc(100%+10px)] z-50 rounded-2xl border border-slate-200 bg-white p-2 text-center shadow-2xl">
<p className="p-3 text-sm text-slate-500">No encontramos resultados para “{query.trim()}”.</p>
<button type="submit" className="w-full rounded-xl bg-ari-marino px-4 py-3 text-sm font-black text-white hover:brightness-110">Buscar “{query.trim()}” en todo el catálogo</button>
</div>
)}
{matches.length > 0 && ( {matches.length > 0 && (
<div className="absolute left-0 right-0 top-[calc(100%+10px)] z-50 overflow-hidden rounded-2xl border border-slate-200 bg-white p-2 shadow-2xl"> <div className="absolute left-0 right-0 top-[calc(100%+10px)] z-50 overflow-hidden rounded-2xl border border-slate-200 bg-white p-2 shadow-2xl">
{matches.map((product) => ( {matches.map((product) => (
@@ -25,7 +25,7 @@ spec:
runAsUser: 1001 runAsUser: 1001
containers: containers:
- name: app - name: app
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.238 image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.240
env: env:
- name: HEADLESS_PROVIDER - name: HEADLESS_PROVIDER
value: medusa value: medusa