Add virtual grid provider coverage

active-uix
dev 5 months ago
parent 859f873eb2
commit 5ebe68d640

@ -47,9 +47,11 @@ Actualizacion 2026-05-15:
- Correccion VirtualList: la compensación de mediciones dinámicas sobre
viewports internos pasa por `ActiveDom.scrollTo(...)` y usa
`scrollOffset + delta` como fuente reactiva.
- Cobertura nueva para VirtualGrid: cálculo de ventana 2D y `scrollToCell`
via `ActiveDom`.
- Validado por fase:
- `npm run check` -> 0 errores, 0 warnings.
- `npm run test` -> 185 archivos, 2083 tests OK.
- `npm run test` -> 186 archivos, 2085 tests OK.
- tests focales de Select/Popover/Toast/RangeCalendar -> 11 tests OK.
- tests focales Dialog/Drawer/Popover/Select -> 10 tests OK.
- `command-provider.svelte.test.ts` -> 2 tests OK.
@ -63,6 +65,7 @@ Actualizacion 2026-05-15:
- `date-range-field-provider.svelte.test.ts` -> 3 tests OK.
- `date-field-provider.svelte.test.ts` -> 7 tests OK.
- `virtual-list-provider.svelte.test.ts` -> 3 tests OK.
- `virtual-grid-provider.svelte.test.ts` -> 2 tests OK.
- guardia `rg "from './.*provider\\.svelte'" src/uix/soma/components -g 'exports.ts'`
-> solo queda `select/components/select-provider.svelte`, que es wrapper
publico, no runtime provider.

@ -480,9 +480,11 @@ Los tests por componente estan creciendo desde las piezas de mayor riesgo. A
orden/min/max, validación custom y foco de label via `ActiveDom`.
- `virtual-list/virtual-list-provider.svelte.test.ts` — cálculo de ventana,
`scrollToIndex` y compensación anti-jump via `ActiveDom`.
- `virtual-grid/virtual-grid-provider.svelte.test.ts` — cálculo de ventana 2D
y `scrollToCell` via `ActiveDom`.
Pendiente: seguir ampliando cobertura por familias de alto riesgo fuera del
bloque fecha/hora/virtualización. `table-core`, `form-core` y el scorer de
bloque fecha/hora y virtualización. `table-core`, `form-core` y el scorer de
Command ya no viven dentro de Soma: se consumen desde `$libs/datagrid`,
`$libs/forms` y `$libs/strings`.

@ -0,0 +1,123 @@
// @vitest-environment jsdom
import { afterEach, describe, expect, it, vi } from 'vitest';
import { createActiveDom } from '$adom';
import { state } from '$libs/reactive';
import type { Morfo } from '$uix/morfo';
import { Soma } from '$soma/core/soma.svelte';
import { createSomaRuntime, type SomaRuntimeSources } from '$soma/runtime.svelte';
import { VirtualGridProvider } from './virtual-grid-provider.svelte';
function withEffectRoot<T>(fn: () => T): { result: T; cleanup: () => void } {
let result!: T;
const cleanup = $effect.root(() => {
result = fn();
});
return { result, cleanup };
}
function installSomaHarness() {
const dom = createActiveDom();
const soma = {
dom,
runtime: (morfo: Morfo, sources: Omit<SomaRuntimeSources, 'dom' | 'eventEngine'>) =>
createSomaRuntime(morfo, {
dom,
translate: (key) => key,
...sources
})
} as unknown as Soma;
vi.spyOn(Soma, 'require').mockReturnValue(soma);
vi.spyOn(VirtualGridProvider.ctx, 'set').mockImplementation((value) => value);
return { dom };
}
function createVirtualGridOpts() {
return {
id: state('virtual-grid-root'),
ref: state<HTMLElement | null>(null),
rowCount: state(10),
columnCount: state(5),
rowSize: state(20),
columnSize: state(50),
rowOverscan: state(1),
columnOverscan: state(1),
getRowKey: state<(index: number) => string | number>((index) => `r${index}`),
getColumnKey: state<(index: number) => string | number>((index) => `c${index}`)
};
}
describe('VirtualGridProvider', () => {
afterEach(() => {
vi.restoreAllMocks();
document.body.innerHTML = '';
});
it('computes 2D virtual cells from viewport and overscan', () => {
const { dom } = installSomaHarness();
const opts = createVirtualGridOpts();
const { result: provider, cleanup } = withEffectRoot(() => VirtualGridProvider.create(opts));
provider.viewportHeight = 60;
provider.viewportWidth = 100;
provider.scrollTop = 30;
provider.scrollLeft = 55;
expect(provider.totalHeight).toBe(200);
expect(provider.totalWidth).toBe(250);
expect(provider.virtualCells).toHaveLength(30);
expect(provider.virtualCells[0]).toEqual({
rowIndex: 0,
columnIndex: 0,
rowStart: 0,
columnStart: 0,
rowSize: 20,
columnSize: 50,
key: 'r0|c0'
});
expect(provider.virtualCells.at(-1)).toEqual({
rowIndex: 5,
columnIndex: 4,
rowStart: 100,
columnStart: 200,
rowSize: 20,
columnSize: 50,
key: 'r5|c4'
});
cleanup();
dom.dispose();
});
it('routes scrollToCell through ActiveDom', () => {
const { dom } = installSomaHarness();
const opts = createVirtualGridOpts();
const viewport = document.createElement('div');
const scrollTo = vi.spyOn(dom, 'scrollTo');
const { result: provider, cleanup } = withEffectRoot(() => VirtualGridProvider.create(opts));
provider.viewportRef = viewport;
provider.viewportHeight = 100;
provider.viewportWidth = 100;
provider.scrollTop = 20;
provider.scrollLeft = 30;
provider.scrollToCell(6, 3, {
rowAlign: 'center',
columnAlign: 'center'
});
expect(scrollTo).toHaveBeenCalledWith(viewport, {
top: 80,
left: 125,
behavior: 'auto'
});
cleanup();
dom.dispose();
});
});
Loading…
Cancel
Save

Powered by TurnKey Linux.