97 lines
3.7 KiB
TypeScript
97 lines
3.7 KiB
TypeScript
|
|
import assert from "node:assert/strict";
|
||
|
|
import { test } from "node:test";
|
||
|
|
|
||
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
||
|
|
|
||
|
|
import { EntityTable } from "./components/entity-list";
|
||
|
|
import { entityListPages, entityListRange } from "./lib/entity-list";
|
||
|
|
|
||
|
|
const items = Array.from({ length: 21 }, (_, index) => ({
|
||
|
|
id: String(index),
|
||
|
|
name: `Persona ${String(index + 1).padStart(2, "0")}`,
|
||
|
|
}));
|
||
|
|
const columns = [
|
||
|
|
{
|
||
|
|
id: "name",
|
||
|
|
label: "Nombre",
|
||
|
|
value: (item: (typeof items)[number]) => item.name,
|
||
|
|
render: (item: (typeof items)[number]) => item.name,
|
||
|
|
hideable: false,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
test("los rangos vacíos y la última página nunca muestran índices fuera del conjunto", () => {
|
||
|
|
assert.deepEqual(entityListRange(0, 5, 10), { page: 0, pages: 1, from: 0, to: 0 });
|
||
|
|
assert.deepEqual(entityListRange(21, 2, 10), { page: 2, pages: 3, from: 21, to: 21 });
|
||
|
|
assert.deepEqual(entityListRange(9, 2, 10), { page: 0, pages: 1, from: 1, to: 9 });
|
||
|
|
assert.deepEqual(entityListPages(0, 12), [0, 1, 2, 3, 4]);
|
||
|
|
assert.deepEqual(entityListPages(11, 12), [7, 8, 9, 10, 11]);
|
||
|
|
assert.deepEqual(entityListPages(0, 1), [0]);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("el listado pagina el conjunto y repite su rango conservando controles accesibles", () => {
|
||
|
|
const html = renderToStaticMarkup(
|
||
|
|
<EntityTable columns={columns} items={items} title="Personas" />
|
||
|
|
);
|
||
|
|
assert.equal(html.split("Mostrando 1-10 de 21 personas").length - 1, 2);
|
||
|
|
assert.ok(html.includes("Persona 10"));
|
||
|
|
assert.equal(html.includes("Persona 11"), false);
|
||
|
|
assert.ok(html.includes('aria-label="Página siguiente"'));
|
||
|
|
assert.ok(html.includes('aria-current="page"'));
|
||
|
|
assert.ok(html.includes('scope="col"'));
|
||
|
|
assert.ok(html.includes("Columnas"));
|
||
|
|
assert.ok(html.includes("Ordenar por"));
|
||
|
|
});
|
||
|
|
|
||
|
|
test("la búsqueda local reduce el conjunto completo antes de paginar y permite limpiarla", () => {
|
||
|
|
const html = renderToStaticMarkup(
|
||
|
|
<EntityTable columns={columns} items={items} search="Persona 21" title="Personas" />
|
||
|
|
);
|
||
|
|
assert.ok(html.includes("Mostrando 1-1 de 1 personas"));
|
||
|
|
assert.ok(html.includes("Persona 21"));
|
||
|
|
assert.ok(html.includes("Limpiar filtros"));
|
||
|
|
assert.equal(html.includes("Persona 01"), false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("una búsqueda controlada conserva los resultados filtrados por la pantalla", () => {
|
||
|
|
const html = renderToStaticMarkup(
|
||
|
|
<EntityTable
|
||
|
|
columns={columns}
|
||
|
|
items={items.slice(0, 1)}
|
||
|
|
onSearchChange={() => undefined}
|
||
|
|
search="criterio externo"
|
||
|
|
title="Personas"
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
assert.ok(html.includes("Mostrando 1-1 de 1 personas"));
|
||
|
|
assert.ok(html.includes("Persona 01"));
|
||
|
|
});
|
||
|
|
|
||
|
|
test("carga, error y búsqueda vacía se distinguen de un listado sin registros", () => {
|
||
|
|
const render = (props: { loading?: boolean; unavailable?: boolean; search?: string }) =>
|
||
|
|
renderToStaticMarkup(
|
||
|
|
<EntityTable
|
||
|
|
columns={columns}
|
||
|
|
emptyMessage="No hay personas."
|
||
|
|
items={[]}
|
||
|
|
title="Personas"
|
||
|
|
{...props}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
assert.ok(render({}).includes("No hay personas."));
|
||
|
|
assert.ok(render({ search: "Ana" }).includes("No hay resultados para estos criterios."));
|
||
|
|
assert.ok(render({ loading: true }).includes('aria-busy="true"'));
|
||
|
|
assert.equal(render({ loading: true }).includes("No hay personas."), false);
|
||
|
|
assert.ok(render({ unavailable: true }).includes("No se ha podido cargar el listado."));
|
||
|
|
assert.equal(render({ unavailable: true }).includes("Mostrando 0-0"), false);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("el rango y la configuración también se traducen en inglés", () => {
|
||
|
|
const html = renderToStaticMarkup(
|
||
|
|
<EntityTable columns={columns} items={[]} locale="en" title="People" />
|
||
|
|
);
|
||
|
|
assert.ok(html.includes("Showing 0-0 of 0 people"));
|
||
|
|
assert.ok(html.includes("Columns"));
|
||
|
|
assert.ok(html.includes("Items per page"));
|
||
|
|
});
|