diff --git a/modules/customers/src/web/shared/hooks/customer-cache-strategy.test.ts b/modules/customers/src/web/shared/hooks/customer-cache-strategy.test.ts new file mode 100644 index 00000000..646649ef --- /dev/null +++ b/modules/customers/src/web/shared/hooks/customer-cache-strategy.test.ts @@ -0,0 +1,141 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { QueryClient } from "@tanstack/react-query"; + +import type { Customer } from "../entities/customer.entity"; +import type { CustomerList } from "../entities/customer-list.entity"; + +import { + getAllCustomerListQueryKeys, + removeCustomerFromListCaches, + syncUpdatedCustomerCaches, +} from "./customer-cache-strategy"; +import { CUSTOMER_QUERY_KEY, LIST_CUSTOMERS_QUERY_KEY } from "./keys"; + +const customer: Customer = { + id: "e2e-customer", + companyId: "e2e-company", + status: "active", + reference: null, + isCompany: true, + name: "Updated customer", + tradeName: null, + tin: null, + address: { + street: null, + street2: null, + city: null, + province: null, + postalCode: null, + country: "ES", + }, + contact: { + primaryEmail: null, + secondaryEmail: null, + primaryPhone: null, + secondaryPhone: null, + primaryMobile: null, + secondaryMobile: null, + fax: null, + website: null, + }, + legalRecord: null, + paymentMethod: null, + paymentTerm: null, + taxRegime: null, + fiscalDefaults: { usesEquivalenceSurcharge: false, usesRetention: false }, + languageCode: "es", + currencyCode: "EUR", +}; + +// Es la query de useCustomerCreateFiscalController que permanece al entrar en edición. +const paymentTermKey = ["customers", "create", "company-default-payment-term", customer.companyId]; +const paymentTermId = "e2e-payment-term"; + +test("sincroniza las listas y el detalle sin tratar el plazo de pago de alta como CustomerList", async () => { + const client = new QueryClient(); + try { + const firstKey = LIST_CUSTOMERS_QUERY_KEY(); + const secondKey = LIST_CUSTOMERS_QUERY_KEY({ pageNumber: 1 }); + const previousRow = { ...customer, name: "Previous customer" }; + const otherRow = { ...customer, id: "other-customer", name: "Other customer" }; + const firstPage: CustomerList = { + items: [previousRow, otherRow], + page: 0, + perPage: 2, + totalItems: 3, + totalPages: 2, + }; + const secondPage: CustomerList = { + items: [previousRow], + page: 1, + perPage: 2, + totalItems: 3, + totalPages: 2, + }; + client.setQueryData(paymentTermKey, paymentTermId); + client.setQueryData(firstKey, firstPage); + client.setQueryData(secondKey, secondPage); + + await syncUpdatedCustomerCaches(client, customer); + + assert.deepEqual(getAllCustomerListQueryKeys(client), [firstKey, secondKey]); + assert.deepEqual(client.getQueryData(CUSTOMER_QUERY_KEY(customer.id)), customer); + for (const key of [firstKey, secondKey]) { + const page = client.getQueryData(key); + assert.ok(page); + assert.equal(page.items[0]?.name, customer.name); + assert.equal(page.totalItems, 3); + assert.equal(page.totalPages, 2); + assert.equal(client.getQueryState(key)?.isInvalidated, true); + } + assert.deepEqual(client.getQueryData(firstKey)?.items[1], otherRow); + assert.equal(firstPage.items[0]?.name, "Previous customer"); + assert.equal(client.getQueryData(paymentTermKey), paymentTermId); + assert.equal(client.getQueryState(paymentTermKey)?.isInvalidated, false); + } finally { + client.clear(); + } +}); + +test("tolera una query de listado pendiente sin datos al sincronizar", async () => { + const client = new QueryClient(); + try { + const key = LIST_CUSTOMERS_QUERY_KEY(); + client.getQueryCache().build(client, { queryKey: key }); + assert.deepEqual(client.getQueriesData({ queryKey: key }), [[key, undefined]]); + + await syncUpdatedCustomerCaches(client, customer); + + assert.equal(client.getQueryData(key), undefined); + assert.deepEqual(client.getQueryData(CUSTOMER_QUERY_KEY(customer.id)), customer); + } finally { + client.clear(); + } +}); + +test("el borrado de filas tampoco recorre la query de plazo de pago", () => { + const client = new QueryClient(); + try { + const key = LIST_CUSTOMERS_QUERY_KEY(); + const page: CustomerList = { + items: [customer], + page: 0, + perPage: 25, + totalItems: 1, + totalPages: 1, + }; + client.setQueryData(paymentTermKey, paymentTermId); + client.setQueryData(key, page); + + const snapshots = removeCustomerFromListCaches(client, customer.id); + + assert.deepEqual(snapshots, [{ key, page }]); + assert.deepEqual(client.getQueryData(key)?.items, []); + assert.equal(client.getQueryData(key)?.totalItems, 0); + assert.equal(client.getQueryData(paymentTermKey), paymentTermId); + } finally { + client.clear(); + } +}); diff --git a/modules/customers/src/web/shared/hooks/keys.ts b/modules/customers/src/web/shared/hooks/keys.ts index 2ca5ade1..2de89214 100644 --- a/modules/customers/src/web/shared/hooks/keys.ts +++ b/modules/customers/src/web/shared/hooks/keys.ts @@ -3,9 +3,9 @@ import { INITIAL_PAGE_INDEX, INITIAL_PAGE_SIZE } from "@repo/rdx-criteria"; import type { QueryKey } from "@tanstack/react-query"; /** - * Prefijo base para listados + * Prefijo exclusivo de CustomerList; las queries auxiliares de alta usan ["customers", "create", ...]. */ -export const LIST_CUSTOMERS_QUERY_KEY_PREFIX = ["customers"] as const; +export const LIST_CUSTOMERS_QUERY_KEY_PREFIX = ["customers:list"] as const; /** * Query key para listado de customers