FactuGES_ERP/docs/testing/frontend-tests-E2E.md

452 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Frontend ERP – Convención de organización y naming de tests E2E
**Estado:** convención adoptada para Playwright y la suite E2E del ERP.
## 1. Propósito
Definir una convención única para organizar, nombrar e identificar los tests E2E del ERP, de forma que sean fáciles de localizar, mantener y relacionar con el módulo y la feature funcional que validan.
## 2. Principio de organización
El primer nivel de directorios bajo `tests/e2e` debe corresponder exactamente con el nombre del módulo propietario existente bajo `/modules`.
Regla:
```txt
tests/e2e/<module>/
```
Ejemplos:
```txt
modules/identity
→ tests/e2e/identity
modules/customers
→ tests/e2e/customers
modules/companies
→ tests/e2e/companies
modules/catalogs
→ tests/e2e/catalogs
modules/customer-invoices
→ tests/e2e/customer-invoices
```
No deben crearse categorías E2E alternativas como:
```txt
auth/
invoices/
settings/
```
si no coinciden con el módulo propietario real.
## 3. Convención de nombres de fichero
El nombre del fichero debe representar la **feature o el flujo funcional probado**. No debe incluir numeración de casos.
Ejemplos:
```txt
login.spec.ts
protected-routes.spec.ts
logout.spec.ts
create-customer.spec.ts
update-customer.spec.ts
```
Se adopta `*.spec.ts` como sufijo estándar.
Al vivir dentro de:
```txt
tests/e2e/
```
no es necesario añadir `e2e` al nombre del fichero.
## 4. Convención de identificadores de casos
Cada test funcional debe tener un identificador estable con este formato:
```txt
<MODULE>-<FEATURE>-<NNN>
```
Donde:
- `MODULE`: nombre lógico del módulo propietario, en mayúsculas.
- `FEATURE`: feature o flujo funcional que agrupa el caso.
- `NNN`: secuencia numérica de tres dígitos comenzando en `001` dentro de la feature.
Ejemplos:
```txt
IDENTITY-LOGIN-001
IDENTITY-LOGIN-002
IDENTITY-ROUTES-001
IDENTITY-LOGOUT-001
```
## 5. Ejemplo: Identity
Estructura:
```txt
tests/e2e/identity/
├── login.spec.ts
├── protected-routes.spec.ts
└── logout.spec.ts
```
Casos:
```txt
IDENTITY-LOGIN-001
Login correcto y persistencia tras recarga
IDENTITY-LOGIN-002
Rechazo de credenciales incorrectas
IDENTITY-ROUTES-001
Acceso a ruta protegida sin sesión
IDENTITY-LOGOUT-001
Cierre de sesión
```
Ejemplo en Playwright:
```ts
test(
"IDENTITY-LOGIN-001: login correcto y persistencia tras recarga",
async ({ page }) => {
// ...
},
);
test(
"IDENTITY-LOGIN-002: rechazo de credenciales incorrectas",
async ({ page }) => {
// ...
},
);
```
## 6. Ejemplos en otros módulos
### Customers
```txt
tests/e2e/customers/create-customer.spec.ts
→ CUSTOMERS-CREATE-001
→ CUSTOMERS-CREATE-002
tests/e2e/customers/update-customer.spec.ts
→ CUSTOMERS-UPDATE-001
```
Ejemplos:
```txt
CUSTOMERS-CREATE-001
Alta válida de cliente
CUSTOMERS-CREATE-002
Validaciones de alta
CUSTOMERS-UPDATE-001
Modificación válida de cliente
```
### Customer Invoices
Para módulos grandes se permite añadir la bounded feature al identificador:
```txt
tests/e2e/customer-invoices/proformas/create-proforma.spec.ts
→ CUSTOMER-INVOICES-PROFORMA-CREATE-001
```
No deben introducirse abreviaturas arbitrarias diferentes para el mismo módulo.
Evitar mezclar, por ejemplo:
```txt
CUSTOMER-INVOICES-...
INVOICES-...
CI-...
```
salvo que en el futuro se acuerde formalmente una abreviatura estable.
## 7. Subdirectorios en módulos grandes
Un módulo grande puede subdividirse por bounded feature, pero el primer nivel bajo `tests/e2e` continúa siendo siempre el módulo propietario.
Ejemplo:
```txt
tests/e2e/customer-invoices/
├── proformas/
├── issued-invoices/
└── recurring-proformas/
```
Correcto:
```txt
tests/e2e/customer-invoices/proformas/
tests/e2e/customer-invoices/issued-invoices/
tests/e2e/customer-invoices/recurring-proformas/
```
Evitar:
```txt
tests/e2e/proformas/
tests/e2e/issued-invoices/
tests/e2e/recurring-proformas/
```
porque perdería la trazabilidad directa con:
```txt
modules/customer-invoices
```
## 8. Reglas de numeración
La numeración:
- se reinicia por feature;
- utiliza siempre tres dígitos: `001`, `002`, `003`...;
- identifica el caso, no su prioridad;
- no determina el orden de ejecución;
- no debe cambiar por reordenar tests dentro del fichero;
- no debe reutilizarse para representar otro escenario funcional diferente.
Ejemplo:
```txt
IDENTITY-LOGIN-001
IDENTITY-LOGIN-002
IDENTITY-LOGIN-003
IDENTITY-ROUTES-001
IDENTITY-ROUTES-002
IDENTITY-LOGOUT-001
```
No usar una única secuencia global como:
```txt
IDENTITY-001
IDENTITY-002
IDENTITY-003
...
```
porque pierde información sobre la feature.
## 9. Naming del test
El identificador debe formar parte del título de `test()`.
Correcto:
```ts
test("IDENTITY-LOGIN-002: rechazo de credenciales incorrectas", async ({
page,
}) => {
// ...
});
```
Evitar:
```ts
test("rechaza credenciales incorrectas", async ({ page }) => {
// ...
});
```
si ese test pertenece al catálogo E2E formal.
El texto posterior al identificador debe describir el comportamiento desde el punto de vista funcional.
## 10. Localización de tests
La inclusión del identificador en el título permite localizar cualquier caso mediante búsqueda textual.
Ejemplo:
```bash
rg -n --glob "*.spec.ts" "IDENTITY-LOGIN-002" tests/e2e
```
Para localizar todos los casos de una feature:
```bash
rg -n --glob "*.spec.ts" "IDENTITY-LOGIN-" tests/e2e
```
Para obtener solo los ficheros:
```bash
rg -l --glob "*.spec.ts" "IDENTITY-LOGIN-002" tests/e2e
```
## 11. Convención de selectores E2E
Los tests no deben depender de textos traducidos.
Orden de preferencia:
```txt
1. id técnico estable
2. data-testid estable
3. atributo técnico estable, por ejemplo name
4. selector CSS técnico y estable, solo excepcionalmente
```
Ejemplos:
```ts
page.locator("#login-email");
page.getByTestId("login-submit");
page.locator('input[name="email"]');
```
Evitar como contrato principal:
```ts
page.getByText("Entrar");
page.getByLabel("Email");
page.getByRole("button", { name: "Entrar" });
```
porque esos textos pueden variar con el locale.
También evitar:
```txt
clases Tailwind visuales
nth-child
selectores dependientes de posición
estructura DOM incidental
IDs generados mediante React.useId()
```
Las clases CSS solo deben utilizarse excepcionalmente cuando sean clases técnicas deliberadamente estables, no clases de presentación.
## 12. Accesibilidad
La estrategia de selectores E2E no sustituye la accesibilidad.
Los componentes deben mantener correctamente:
```txt
label
htmlFor
role
aria-label
aria-describedby
aria-live
```
cuando corresponda.
Los atributos técnicos para testing son un contrato complementario.
## 13. Independencia de los tests
Cada caso E2E debe poder ejecutarse:
```txt
de forma aislada
en cualquier orden
junto con el resto de la suite
```
El identificador:
```txt
IDENTITY-LOGIN-002
```
no significa que el test dependa de:
```txt
IDENTITY-LOGIN-001
```
Los tests no deben depender del estado dejado por casos anteriores.
## 14. Relación entre directorio, fichero y caso
Regla general:
```txt
Directorio
→ módulo propietario
Fichero
→ feature o flujo funcional
Caso
→ MODULE-FEATURE-NNN
```
Ejemplo:
```txt
tests/e2e/identity/login.spec.ts
→ IDENTITY-LOGIN-001
→ IDENTITY-LOGIN-002
tests/e2e/identity/protected-routes.spec.ts
→ IDENTITY-ROUTES-001
tests/e2e/identity/logout.spec.ts
→ IDENTITY-LOGOUT-001
```
## 15. Criterio para nuevas features
Antes de crear un nuevo test:
1. identificar el módulo propietario real bajo `/modules`;
2. localizar o crear el fichero correspondiente al flujo funcional;
3. determinar el nombre estable de la feature;
4. asignar el siguiente `NNN` disponible dentro de esa feature;
5. incluir el identificador completo en el título de `test()`.
No crear nuevos prefijos para pequeñas variaciones del mismo flujo si no existe una diferencia funcional clara.
## 16. Regla mental final
```txt
tests/e2e/<module>/<feature>.spec.ts
<MODULE>-<FEATURE>-<NNN>
```
Ejemplo:
```txt
tests/e2e/identity/login.spec.ts
IDENTITY-LOGIN-001
```
La estructura física indica **quién es propietario del comportamiento**.
El fichero indica **qué flujo se está probando**.
El identificador indica **qué caso funcional concreto se está ejecutando**.