121 lines
4.0 KiB
TypeScript
121 lines
4.0 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import * as domtools from '../ts/index.js';
|
|
|
|
const cleanupGlobalDomTools = () => {
|
|
try {
|
|
domtools.DomTools.getGlobalDomToolsSync().dispose();
|
|
} catch {
|
|
// No global domtools instance exists yet.
|
|
}
|
|
};
|
|
|
|
const getStyleCount = () => document.head.querySelectorAll('style').length;
|
|
|
|
tap.test('setupDomTools reuses the global singleton', async () => {
|
|
cleanupGlobalDomTools();
|
|
const firstInstance = await domtools.DomTools.setupDomTools();
|
|
const secondInstance = await domtools.DomTools.setupDomTools();
|
|
|
|
expect(firstInstance).toBeInstanceOf(domtools.DomTools);
|
|
expect(firstInstance === secondInstance).toBeTrue();
|
|
expect(domtools.DomTools.getGlobalDomToolsSync() === firstInstance).toBeTrue();
|
|
|
|
cleanupGlobalDomTools();
|
|
});
|
|
|
|
tap.test('ignoreGlobal creates an isolated instance without replacing the global one', async () => {
|
|
cleanupGlobalDomTools();
|
|
const globalInstance = await domtools.DomTools.setupDomTools();
|
|
const isolatedInstance = await domtools.DomTools.setupDomTools({
|
|
ignoreGlobal: true,
|
|
});
|
|
|
|
await globalInstance.domToolsReady.promise;
|
|
await globalInstance.domReady.promise;
|
|
await isolatedInstance.domToolsReady.promise;
|
|
await isolatedInstance.domReady.promise;
|
|
|
|
expect(globalInstance === isolatedInstance).toBeFalse();
|
|
expect(domtools.DomTools.getGlobalDomToolsSync() === globalInstance).toBeTrue();
|
|
expect(Boolean(isolatedInstance.keyboard)).toBeTrue();
|
|
|
|
isolatedInstance.dispose();
|
|
cleanupGlobalDomTools();
|
|
});
|
|
|
|
tap.test('runOnce shares the first result across concurrent callers', async () => {
|
|
cleanupGlobalDomTools();
|
|
const domtoolsInstance = await domtools.DomTools.setupDomTools({
|
|
ignoreGlobal: true,
|
|
});
|
|
let runCount = 0;
|
|
|
|
const [firstResult, secondResult] = await Promise.all([
|
|
domtoolsInstance.runOnce('test-run-once', async () => {
|
|
runCount += 1;
|
|
await new Promise<void>((resolve) => window.setTimeout(resolve, 10));
|
|
return 'shared-result';
|
|
}),
|
|
domtoolsInstance.runOnce('test-run-once', async () => {
|
|
runCount += 1;
|
|
return 'unexpected-result';
|
|
}),
|
|
]);
|
|
|
|
expect(runCount).toEqual(1);
|
|
expect(firstResult).toEqual('shared-result');
|
|
expect(secondResult).toEqual('shared-result');
|
|
|
|
domtoolsInstance.dispose();
|
|
});
|
|
|
|
tap.test('elementBasic setup waits for global styles and keeps injection idempotent', async () => {
|
|
cleanupGlobalDomTools();
|
|
const styleCountBefore = getStyleCount();
|
|
|
|
const firstInstance = await domtools.elementBasic.setup();
|
|
const secondInstance = await domtools.elementBasic.setup();
|
|
|
|
await firstInstance.globalStylesReady.promise;
|
|
|
|
expect(firstInstance === secondInstance).toBeTrue();
|
|
expect(getStyleCount() - styleCountBefore).toEqual(1);
|
|
|
|
firstInstance.dispose();
|
|
expect(getStyleCount()).toEqual(styleCountBefore);
|
|
expect(() => domtools.DomTools.getGlobalDomToolsSync()).toThrow();
|
|
});
|
|
|
|
tap.test('keyboard combos still emit through the public key enum API', async () => {
|
|
const domtoolsInstance = await domtools.DomTools.setupDomTools({
|
|
ignoreGlobal: true,
|
|
});
|
|
await domtoolsInstance.domReady.promise;
|
|
|
|
const keyboard = domtoolsInstance.keyboard!;
|
|
const events: KeyboardEvent[] = [];
|
|
const subscription = keyboard.on([keyboard.keyEnum.Ctrl, keyboard.keyEnum.S]).subscribe((event) => {
|
|
events.push(event);
|
|
});
|
|
|
|
keyboard.triggerKeyPress([keyboard.keyEnum.Ctrl, keyboard.keyEnum.S]);
|
|
|
|
expect(events).toHaveLength(1);
|
|
expect(events[0].key).toEqual('s');
|
|
expect(events[0].ctrlKey).toBeTrue();
|
|
|
|
subscription.unsubscribe();
|
|
domtoolsInstance.dispose();
|
|
});
|
|
|
|
tap.test('plugin namespace exports remain available for downstream consumers', async () => {
|
|
expect(domtools.plugins.smartdelay.delayFor).toBeDefined();
|
|
expect(domtools.plugins.smartstate.Smartstate).toBeDefined();
|
|
expect(domtools.plugins.smartpromise.defer).toBeDefined();
|
|
expect(domtools.plugins.smartrouter.SmartRouter).toBeDefined();
|
|
expect(domtools.plugins.smartrx.rxjs.Subject).toBeDefined();
|
|
expect(domtools.plugins.smarturl.Smarturl).toBeDefined();
|
|
});
|
|
|
|
export default tap.start();
|