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

6.8 KiB

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:

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).

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_datepickup_datedelivery_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_invfactor.
  • 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 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.