feat(api): implement javascript-first architecture for cache compatibility

- Add REST endpoint GET /roi-theme/v1/adsense-placement/visibility
- Add Domain layer: UserContext, VisibilityDecision, AdsenseSettings VOs
- Add Application layer: CheckAdsenseVisibilityUseCase
- Add Infrastructure: AdsenseVisibilityChecker, Controller, Enqueuer
- Add JavaScript controller with localStorage caching
- Add test plan for production validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-12-11 13:03:14 -06:00
parent 8936670451
commit 26546e1d69
13 changed files with 1743 additions and 1 deletions

View File

@@ -0,0 +1,545 @@
# Plan de Pruebas: AdSense JavaScript-First Architecture
> **NOTA IMPORTANTE - PROTOCOLO DE PRUEBAS**
>
> Las pruebas se ejecutan en el servidor de PRODUCCION.
> Si hay algo que corregir, se modifica en LOCAL y luego se despliega.
>
> **PROHIBIDO**: Modificar codigo directamente en produccion.
> **PERMITIDO**: Solo ejecutar pruebas y verificaciones en produccion.
>
> Flujo correcto:
> 1. Ejecutar prueba en produccion
> 2. Si falla, corregir en local
> 3. Desplegar cambios a produccion
> 4. Re-ejecutar prueba
---
## Resumen de Pruebas
| ID | Categoria | Descripcion | Criterio de Aceptacion |
|----|-----------|-------------|------------------------|
| T01 | Endpoint REST | Endpoint registrado y accesible | HTTP 200 con JSON valido |
| T02 | Endpoint REST | Headers anti-cache presentes | Cache-Control, Pragma, Expires |
| T03 | Endpoint REST | Parametro post_id requerido | HTTP 400 sin post_id |
| T04 | Endpoint REST | post_id=0 valido (archivos/home) | HTTP 200 con post_id=0 |
| T05 | Visibilidad | Componente deshabilitado | show_ads=false, reason=component_disabled |
| T06 | Visibilidad | Usuario anonimo sin exclusiones | show_ads=true, reasons=[] |
| T07 | Visibilidad | Usuario logueado excluido | show_ads=false, reason=logged_in_excluded |
| T08 | Visibilidad | Rol excluido | show_ads=false, reason=role_excluded |
| T09 | Visibilidad | Post excluido | show_ads=false, reason=post_excluded |
| T10 | JavaScript | Script cargado en frontend | roiAdsenseConfig definido |
| T11 | JavaScript | Cache localStorage funciona | Datos guardados correctamente |
| T12 | JavaScript | Fallback cuando error | Ads se muestran en error |
| T13 | Feature Flag | Modo deshabilitado = legacy | No llama endpoint |
| T14 | Feature Flag | Modo habilitado = JS-First | Llama endpoint |
| T15 | Clean Arch | Value Objects inmutables | No WordPress en Domain |
| T16 | Clean Arch | Interface en Domain | AdsenseVisibilityCheckerInterface existe |
---
## Pruebas Detalladas
### T01: Endpoint REST Registrado y Accesible
**Categoria**: Endpoint REST
**Prioridad**: CRITICA
**Spec Reference**: Requirement: Endpoint REST Visibility
**Pasos**:
1. Abrir navegador o usar curl
2. Acceder a: `https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=1`
**Resultado Esperado**:
- HTTP Status: 200
- Content-Type: application/json
- Body contiene: `show_ads`, `reasons`, `cache_seconds`, `timestamp`
**Comando de Prueba**:
```bash
curl -i "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=1"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T02: Headers Anti-Cache Presentes
**Categoria**: Endpoint REST
**Prioridad**: ALTA
**Spec Reference**: Scenario: Headers anti-cache obligatorios
**Pasos**:
1. Hacer request al endpoint
2. Verificar headers de respuesta
**Resultado Esperado**:
- `Cache-Control: no-store, no-cache, must-revalidate, max-age=0`
- `Pragma: no-cache`
- `Expires: Thu, 01 Jan 1970 00:00:00 GMT` o `0`
- `Vary: Cookie`
**Comando de Prueba**:
```bash
curl -I "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=1"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T03: Parametro post_id Requerido
**Categoria**: Endpoint REST
**Prioridad**: ALTA
**Spec Reference**: Scenario: Parametros del endpoint
**Pasos**:
1. Hacer request SIN post_id
2. Verificar respuesta de error
**Resultado Esperado**:
- HTTP Status: 400 (Bad Request)
- Body contiene mensaje de error indicando que post_id es requerido
**Comando de Prueba**:
```bash
curl -i "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T04: post_id=0 Valido para Paginas de Archivo
**Categoria**: Endpoint REST
**Prioridad**: ALTA
**Spec Reference**: Scenario: Parametros del endpoint (validate_callback >= 0)
**Pasos**:
1. Hacer request con post_id=0
2. Verificar que responde correctamente
**Resultado Esperado**:
- HTTP Status: 200
- Body contiene decision de visibilidad valida
**Comando de Prueba**:
```bash
curl -i "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=0"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T05: Componente Deshabilitado Retorna False
**Categoria**: Visibilidad
**Prioridad**: ALTA
**Spec Reference**: Scenario: Componente deshabilitado
**Pre-condicion**:
- Deshabilitar componente en admin (is_enabled = false)
**Pasos**:
1. Deshabilitar adsense-placement en admin
2. Hacer request al endpoint
3. Verificar respuesta
**Resultado Esperado**:
```json
{
"show_ads": false,
"reasons": ["component_disabled"],
"cache_seconds": 3600
}
```
**Comando de Prueba**:
```bash
curl "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=1"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T06: Usuario Anonimo Sin Exclusiones Ve Ads
**Categoria**: Visibilidad
**Prioridad**: CRITICA
**Spec Reference**: Scenario: Usuario anonimo sin exclusiones
**Pre-condicion**:
- Componente habilitado
- javascript_first_mode habilitado
- Sin exclusiones configuradas
- No estar logueado
**Pasos**:
1. Abrir navegador en modo incognito
2. Acceder a un post del sitio
3. Verificar respuesta del endpoint
**Resultado Esperado**:
```json
{
"show_ads": true,
"reasons": [],
"cache_seconds": 60
}
```
**Comando de Prueba**:
```bash
curl "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=1"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T07: Usuario Logueado Excluido
**Categoria**: Visibilidad
**Prioridad**: ALTA
**Spec Reference**: Scenario: Usuario logueado excluido
**Pre-condicion**:
- Activar "Ocultar para usuarios logueados" en admin
**Pasos**:
1. Loguearse en WordPress
2. Copiar cookies de sesion
3. Hacer request con cookies
**Resultado Esperado**:
```json
{
"show_ads": false,
"reasons": ["logged_in_excluded"],
"cache_seconds": 300
}
```
**Verificacion Manual**:
1. Loguearse en wp-admin
2. Visitar un post en el frontend
3. Abrir DevTools > Network
4. Buscar request a `/visibility`
5. Verificar respuesta
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T08: Rol Excluido
**Categoria**: Visibilidad
**Prioridad**: ALTA
**Spec Reference**: Scenario: Rol de usuario excluido
**Pre-condicion**:
- Agregar "administrator" a roles excluidos en admin
**Pasos**:
1. Loguearse como administrator
2. Visitar un post
3. Verificar respuesta del endpoint
**Resultado Esperado**:
```json
{
"show_ads": false,
"reasons": ["role_excluded"],
"cache_seconds": 300
}
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T09: Post Excluido por ID
**Categoria**: Visibilidad
**Prioridad**: ALTA
**Spec Reference**: Scenario: Post excluido por ID
**Pre-condicion**:
- Agregar un ID de post a "IDs de posts excluidos" en admin
**Pasos**:
1. Anotar el ID del post excluido (ej: 123)
2. Hacer request con ese post_id
3. Verificar respuesta
**Resultado Esperado**:
```json
{
"show_ads": false,
"reasons": ["post_excluded"],
"cache_seconds": 60
}
```
**Comando de Prueba**:
```bash
curl "https://analisisdepreciosunitarios.com/wp-json/roi-theme/v1/adsense-placement/visibility?post_id=123"
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T10: Script JavaScript Cargado
**Categoria**: JavaScript
**Prioridad**: CRITICA
**Spec Reference**: Scenario: Configuracion via wp_localize_script
**Pre-condicion**:
- javascript_first_mode habilitado
**Pasos**:
1. Visitar un post en el frontend
2. Abrir DevTools > Console
3. Escribir: `window.roiAdsenseConfig`
**Resultado Esperado**:
- Objeto definido con propiedades:
- `endpoint`: URL del endpoint REST
- `postId`: ID del post actual
- `nonce`: String no vacio
- `featureEnabled`: true
- `debug`: boolean
**Verificacion Alternativa**:
```javascript
// En consola del navegador
console.log(window.roiAdsenseConfig);
console.log(typeof window.roiAdsenseVisibility);
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T11: Cache localStorage Funciona
**Categoria**: JavaScript
**Prioridad**: ALTA
**Spec Reference**: Scenario: Cache en localStorage
**Pasos**:
1. Visitar un post (primera vez)
2. Abrir DevTools > Application > Local Storage
3. Buscar key `roi_adsense_visibility`
4. Recargar pagina
5. Verificar en Network que NO hay nueva llamada al endpoint
**Resultado Esperado**:
- localStorage contiene:
```json
{
"show_ads": true,
"reasons": [],
"timestamp": 1733900000,
"cache_seconds": 60
}
```
- Segunda carga NO hace request al endpoint (usa cache)
**Verificacion en Consola**:
```javascript
localStorage.getItem('roi_adsense_visibility');
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T12: Fallback en Error de Red
**Categoria**: JavaScript
**Prioridad**: ALTA
**Spec Reference**: Scenario: Fallback strategy cached-or-show
**Pasos**:
1. Limpiar localStorage
2. Abrir DevTools > Network
3. Habilitar "Offline" mode
4. Visitar un post
5. Verificar comportamiento
**Resultado Esperado**:
- Los ads se muestran (fallback = show)
- No hay error en consola (error manejado gracefully)
**Verificacion Alternativa**:
```javascript
// Limpiar cache
window.roiAdsenseVisibility.clearCache();
// Recargar con network offline
```
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T13: Feature Flag Deshabilitado = Modo Legacy
**Categoria**: Feature Flag
**Prioridad**: ALTA
**Spec Reference**: Scenario: Feature flag deshabilitado
**Pre-condicion**:
- Deshabilitar javascript_first_mode en admin
**Pasos**:
1. Deshabilitar javascript_first_mode
2. Visitar un post
3. Verificar en Network que NO hay llamada al endpoint
**Resultado Esperado**:
- `roiAdsenseConfig.featureEnabled` = false
- No hay request a `/visibility` endpoint
- Ads se muestran inmediatamente (modo legacy)
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T14: Feature Flag Habilitado = JS-First
**Categoria**: Feature Flag
**Prioridad**: ALTA
**Spec Reference**: Scenario: Feature flag habilitado
**Pre-condicion**:
- Habilitar javascript_first_mode en admin
**Pasos**:
1. Habilitar javascript_first_mode
2. Limpiar cache (localStorage y pagina)
3. Visitar un post
4. Verificar en Network que SI hay llamada al endpoint
**Resultado Esperado**:
- `roiAdsenseConfig.featureEnabled` = true
- Request a `/visibility` endpoint presente
- Ads se muestran/ocultan segun respuesta
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T15: Value Objects Sin Dependencias WordPress
**Categoria**: Clean Architecture
**Prioridad**: MEDIA
**Spec Reference**: Scenario: Value Object VisibilityDecision en Domain
**Verificacion**:
Revisar que los archivos NO contengan funciones de WordPress:
**Archivos a verificar**:
- `Domain/ValueObjects/UserContext.php`
- `Domain/ValueObjects/VisibilityDecision.php`
- `Domain/ValueObjects/AdsenseSettings.php`
- `Domain/Contracts/AdsenseVisibilityCheckerInterface.php`
- `Application/UseCases/CheckAdsenseVisibilityUseCase.php`
**Resultado Esperado**:
- Sin `get_`, `wp_`, `is_user_logged_in`, `WP_*` classes
- Solo PHP puro y tipos del proyecto
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
### T16: Interface en Domain
**Categoria**: Clean Architecture
**Prioridad**: MEDIA
**Spec Reference**: Scenario: Interface en Domain
**Verificacion**:
El archivo `Domain/Contracts/AdsenseVisibilityCheckerInterface.php` debe:
- Existir en la ruta correcta
- Definir metodo `check(int $postId, UserContext $userContext): VisibilityDecision`
- NO referenciar WordPress
**Estado**: [ ] Pendiente
**Resultado**:
**Notas**:
---
## Checklist de Despliegue Pre-Pruebas
Antes de ejecutar las pruebas, verificar:
- [ ] Codigo desplegado a produccion via FTP/SSH
- [ ] Cache de pagina limpiado
- [ ] javascript_first_mode habilitado en admin
- [ ] Componente adsense-placement habilitado
- [ ] Schema sincronizado en BD (campo javascript_first_mode existe)
---
## Registro de Ejecucion
| Fecha | Tester | Pruebas Ejecutadas | Pasadas | Fallidas | Notas |
|-------|--------|-------------------|---------|----------|-------|
| | | | | | |
---
## Defectos Encontrados
| ID | Prueba | Descripcion | Severidad | Estado | Correccion |
|----|--------|-------------|-----------|--------|------------|
| | | | | | |
---
## Historial de Versiones
| Version | Fecha | Cambios |
|---------|-------|---------|
| 1.0 | 2025-12-11 | Plan inicial basado en spec v1.5 |