Add alert dialog provider coverage

active-uix
dev 5 months ago
parent 3ceb94619a
commit fe61f5be9b

@ -129,9 +129,11 @@ Actualizacion 2026-05-15:
delete/clear triggers y props de input/control.
- Cobertura nueva para Editable: activación preview/trigger, foco via
`ActiveDom`, commit/cancel por teclado/blur y guards disabled/readonly.
- Cobertura nueva para AlertDialog: contratos action/cancel, labels
traducidos/override y cierre delegado al Dialog base.
- Validado por fase:
- `npm run check` -> 0 errores, 0 warnings.
- `npm run test` -> 225 archivos, 2224 tests OK.
- `npm run test` -> 226 archivos, 2226 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.
@ -185,6 +187,7 @@ Actualizacion 2026-05-15:
- `feed-provider.svelte.test.ts` -> 3 tests OK.
- `tags-input-provider.svelte.test.ts` -> 3 tests OK.
- `editable-provider.svelte.test.ts` -> 3 tests OK.
- `alert-dialog-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.

@ -561,6 +561,8 @@ Los tests por componente estan creciendo desde las piezas de mayor riesgo. A
navegación de tags, delete/clear triggers y props de input/control.
- `editable/editable-provider.svelte.test.ts` — activación preview/trigger,
foco via `ActiveDom`, commit/cancel por teclado/blur y guards.
- `alert-dialog/alert-dialog-provider.svelte.test.ts` — contratos
action/cancel, labels traducidos/override y cierre delegado a Dialog.
Pendiente: seguir ampliando cobertura por el resto del catalogo Soma, ya por
componentes de riesgo medio y familias menos centrales. `table-core`,

@ -0,0 +1,134 @@
// @vitest-environment jsdom
import { tick } from 'svelte';
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 { DialogProvider } from '$soma/components/dialog/dialog-provider.svelte';
import {
AlertDialogActionProvider,
AlertDialogCancelProvider
} from './alert-dialog-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,
langs: {
ts: vi.fn((key: string) => (key.includes('cancel') ? 'Cancel' : 'Confirm'))
},
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);
return { dom };
}
function actionOpts(el: HTMLButtonElement, ariaLabel: string | undefined = undefined) {
return {
id: state('alert-action'),
ref: state<HTMLElement | null>(el),
ariaLabel: state(ariaLabel)
};
}
function cancelOpts(el: HTMLButtonElement, ariaLabel: string | undefined = undefined) {
return {
id: state('alert-cancel'),
ref: state<HTMLElement | null>(el),
ariaLabel: state(ariaLabel)
};
}
describe('AlertDialogProvider parts', () => {
afterEach(() => {
vi.restoreAllMocks();
document.body.innerHTML = '';
});
it('projects action/cancel contracts and closes the backing Dialog', async () => {
const { dom } = installSomaHarness();
const handleClose = vi.fn();
vi.spyOn(DialogProvider, 'require').mockReturnValue({
handleClose
} as unknown as DialogProvider);
const actionEl = document.createElement('button');
const cancelEl = document.createElement('button');
document.body.append(actionEl, cancelEl);
const actionOptions = actionOpts(actionEl);
const cancelOptions = cancelOpts(cancelEl, 'Keep item');
const { result, cleanup } = withEffectRoot(() => {
const action = AlertDialogActionProvider.create(actionOptions);
const cancel = AlertDialogCancelProvider.create(cancelOptions);
return { action, cancel };
});
expect(result.action.resolvedAriaLabel).toBe('Confirm');
expect(result.cancel.resolvedAriaLabel).toBe('Keep item');
expect(result.action.props).toMatchObject({
'data-alert-dialog-action': '',
onclick: result.action.onclick
});
expect(result.cancel.props).toMatchObject({
'data-alert-dialog-cancel': '',
onclick: result.cancel.onclick
});
await tick();
expect(actionEl.getAttribute('type')).toBe('button');
expect(actionEl.getAttribute('aria-label')).toBe('Confirm');
expect(cancelEl.getAttribute('type')).toBe('button');
expect(cancelEl.getAttribute('aria-label')).toBe('Keep item');
result.action.onclick({ currentTarget: actionEl } as never);
result.cancel.onclick({ currentTarget: cancelEl } as never);
expect(handleClose).toHaveBeenCalledTimes(2);
cleanup();
dom.dispose();
});
it('keeps aria-label reactive to explicit overrides', async () => {
const { dom } = installSomaHarness();
vi.spyOn(DialogProvider, 'require').mockReturnValue({
handleClose: vi.fn()
} as unknown as DialogProvider);
const actionEl = document.createElement('button');
document.body.appendChild(actionEl);
const opts = actionOpts(actionEl);
const { result: action, cleanup } = withEffectRoot(() =>
AlertDialogActionProvider.create(opts)
);
await tick();
expect(actionEl.getAttribute('aria-label')).toBe('Confirm');
opts.ariaLabel.current = 'Delete account';
await tick();
expect(action.resolvedAriaLabel).toBe('Delete account');
expect(actionEl.getAttribute('aria-label')).toBe('Delete account');
cleanup();
dom.dispose();
});
});
Loading…
Cancel
Save

Powered by TurnKey Linux.