addons-cm/website_sale_aplicoop/COBERTURA_TESTS_PENDIENTE.md
GitHub Copilot 3e4bd5e5db [ADD] website_sale_aplicoop: restore the test coverage lost with the dead code
The dead-code cleanup dropped 11 test files that were never wired into
tests/__init__.py. Reviewing what they covered turned up real holes, so the
worthwhile ones come back, rewritten against the current schema.

Blacklists were the serious gap: product, supplier and category exclusions
have absolute priority over product discovery and nothing exercised them.
The old file had two separate defects. Its supplier fixtures wrote
`main_seller_id` directly, but product_main_seller computes that field from
`variant_seller_ids`, so the compute reset it to False and the blacklist had
nothing to exclude; they now create real supplierinfo records. Worse, four
whole classes asserted against `group_order.product_ids` -- the m2m *input* --
instead of the discovery result, so they set `category_ids` and then checked a
field they never touched. Those go through `_get_products_for_group_order`
now, and three tests that had no assertions at all got some.

The remaining three failures were test bugs too, all Odoo 17->18 leftovers:

* Date cases assumed `pickup_date` derives from `start_date`. The chain is
  cutoff -> pickup -> delivery, and a recurring order whose start date has
  passed rolls forward to the current cycle, so a 2024 order has no 2024
  pickup. The new file anchors on future dates and finds the next 29 February
  dynamically, with a class documenting the roll-forward itself.
* `/eskaera/labels` is `type="json"`; the old test hit it with a plain GET and
  read the resulting 400 as a bug. It is called over JSON-RPC now, and a test
  pins the 400 so nobody repeats it. Also `uom.uom.categ` -> `uom.category`.
* `price_include` is computed in 18.0, so fixtures must set
  `price_include_override`. On top of that `_get_price` filters taxes by
  company and defaults to `env.company`, not the fixture's, which left the
  tax list empty -- `tax_included` was False for the wrong reason.

Two of the portal tests were passing for the wrong reason as well: the access
guard bounced them to /eskaera, which also answers 200. Membership has to be
set from the member side with `is_group`, and a new test checks the final URL
rather than the status alone. Each fixture that can silently build the wrong
thing now carries a guard test.

Left out on purpose: three files were unimplemented placeholders, and
test_draft_persistence still deserves recovering (see the notes file).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 17:24:31 +02:00

147 lines
6.8 KiB
Markdown

# Cobertura de tests — website_sale_aplicoop
Estado tras recuperar y reescribir los tests que se habían perdido con la limpieza
de código muerto (commit `b3999e2`).
La suite quedó en verde y creció en unos 90 tests respecto a los 270 que había
tras la limpieza.
Los ficheros originales, si alguna vez hacen falta:
```bash
git show b3999e2^:website_sale_aplicoop/tests/<fichero>.py
```
---
## Recuperado y arreglado
### 1. `test_product_discovery.py` — blacklists y descubrimiento (46 tests)
Era el hueco grave: **ningún test cubría las tres blacklists**, que son lógica viva
con "prioridad absoluta" sobre el descubrimiento
([group_order.py:571-627](models/group_order.py#L571-L627)).
Dos bugs distintos en el fichero original:
- **`TestSupplierBlacklist` (6 fallos)**: el fixture escribía `main_seller_id` en el
`create` del template, pero en el addon OCA `product_main_seller` ese campo es
*computed + store* derivado de `variant_seller_ids` — el compute lo pisaba a `False`,
los productos quedaban sin proveedor principal y la blacklist no tenía nada que
excluir. Arreglado creando `product.supplierinfo` de verdad, más un test-guarda
(`test_main_seller_is_computed_from_supplierinfo`) para que no vuelva a pasar en
silencio.
- **Cuatro clases enteras no probaban el descubrimiento**: hacían aserciones contra
`group_order.product_ids`, que es el campo m2m de *entrada*, no el resultado. Es
decir, asignaban `category_ids` y comprobaban `product_ids`, así que sólo podían
fallar; y algunas "pasaban" por el motivo equivocado (el campo estaba vacío de
todos modos). Tres tests no tenían ni una aserción. Todo reescrito contra
`_get_products_for_group_order`.
Añadido de paso: productos archivados, pedido sin ninguna fuente, id inexistente, y
el contrato de ordenación real (`is_out_of_stock`, `website_sequence`, nombre).
### 2. `test_date_edge_cases.py` — calendario (12 tests)
Sustituye al antiguo `test_edge_cases.py`. Los 4 fallos que había eran **del test**,
no de producción: daban por hecho que `pickup_date` se calcula desde `start_date`,
cuando en realidad la cadena es `cutoff_date``pickup_date``delivery_date`, y
para un pedido recurrente con `start_date` pasada la referencia pasa a ser **hoy**
(el ciclo avanza al actual). Un pedido de 2024 no tiene fecha de recogida en 2024.
Los nuevos anclan en fechas **futuras** para que el avance de ciclo no mueva el caso
bajo los pies, y buscan el próximo 29-F dinámicamente (no hay fechas quemadas que
caduquen). Cubren: recogida justo en 29-F, ciclo que cruza el 29-F, entrega el 1-M,
cruce de mes y de año, último día de mes, rejilla mensual desde un ancla de 31-E y
en febrero bisiesto. `TestRollForwardBehaviour` documenta el avance de ciclo, que es
justo lo que el test viejo malinterpretaba.
### 3. `test_portal_routes.py` — humo HTTP con usuario portal (8 tests)
Une los tres ficheros portal borrados. Los fallos eran del test:
- **`/eskaera/labels` devolvía 400**: la ruta es `type="json"` y el test la llamaba
con un GET plano. Odoo responde 400 correctamente. Ahora se llama por JSON-RPC
(`make_jsonrpc_request`), y hay un test que fija ese 400 del GET para que nadie
repita el error.
- **`uom.uom.categ` no existe** en Odoo 18 (es `uom.category`), y `factor_inv`
`factor`.
- **La afiliación al grupo no se aplicaba**: hay que poner `is_group=True` en el
grupo y asignar `group_ids` desde el *miembro* (es el idioma que usa
`test_record_rules.py`). Sin eso el guard rebotaba a `/eskaera`.
Ojo con esto último: el smoke test original sólo miraba `status_code == 200`, y el
rebote a la lista **también** devuelve 200 — pasaba sin que el socio entrase nunca a
la tienda. Añadido `test_shop_page_is_not_bounced_to_the_list`, que comprueba la URL
final.
### 4. `test_price_with_taxes_included.py` — impuestos (14 tests)
Dos causas, ambas del test:
- **`price_include` es computed en Odoo 18**, derivado de `price_include_override`
(Selection `tax_included`/`tax_excluded`). El fixture escribía `price_include=True`
y se descartaba en silencio. Añadido `test_price_include_is_driven_by_the_override`
como guarda.
- **`_get_price` filtra los impuestos por compañía**, y su parámetro `company` cae
por defecto en `self.env.company`. Como el fixture crea una compañía propia, la
lista de impuestos salía **vacía** y `tax_included` era siempre `False`. Nótese que
`test_oca_get_price_returns_base_without_tax` pasaba por este motivo equivocado.
Ahora todas las llamadas van por un helper que pasa `company=self.company`.
---
## Sin recuperar (no había nada que rescatar)
Tres ficheros eran plantillas sin implementar — setUp seguido de métodos con
`# Placeholder: will be implemented...` y cero aserciones, o aserciones sobre
diccionarios simulados en vez de llamar al controlador:
- `test_endpoints.py`
- `test_helper_methods_phase1.py`
- `test_phase2_eskaera_shop.py`
---
## Pendiente
### `test_draft_persistence.py` — persistencia de borradores
Lo único de los 11 ficheros que aún no se ha rehecho. Cubría casos que hoy no cubre
nadie (`test_save_order_endpoints.py` y `test_group_order_status_endpoint.py` cubren
el guardado y el ciclo, no esto):
- **el precio del borrador es una foto fija**: cambiar `list_price` después no altera
el borrador ya guardado. El más valioso — es una garantía de negocio real (al socio
se le respeta el precio que vio) y ahora mismo nada la protege.
- borrador con producto archivado después de guardarlo
- borrador de un pedido ya cerrado / de hace 6 meses
- un borrador no es visible para otro usuario
- recuento de borradores por usuario
Sólo 2 de sus 14 tests fallaban, así que la recuperación debería ser barata.
### Huecos menores
- Transiciones de estado **ilegales** (draft→closed, cancelled→open). La suite cubre
las legales en `test_group_order.py`.
- `available_products_count` fuera del contexto de blacklists (dentro de ellas ya
está cubierto).
Nota: las constraints `_check_company_groups` y `_check_dates` **sí** están cubiertas
(`test_multi_company.py:147`, `test_group_order.py:66`) — no son hueco.
---
## Conclusión sobre los "posibles bugs de producción"
Los tres que quedaron marcados para investigar (fechas 29-F, `/eskaera/labels` 400,
`tax_included`) resultaron ser **todos bugs de los tests**, en su mayoría restos de la
migración 17→18: `is_supplier`, `main_seller_id`, `uom.uom.categ`, `factor_inv`,
`price_include`. No apareció ningún bug de producción.
Lo que sí apareció, y es más incómodo, son **tests que pasaban por el motivo
equivocado** — el smoke test del portal que se conformaba con el rebote, y
`test_oca_get_price_returns_base_without_tax` que verificaba `tax_included == False`
sobre una lista de impuestos vacía. Por eso cada arreglo lleva ahora un test-guarda
que falla si el fixture deja de construir lo que dice construir.