fix: Kiku field grouping, frequency particles, sidebar media, Yomitan popup visibility (#91)

This commit is contained in:
2026-05-27 01:40:48 -07:00
committed by GitHub
parent efe50ed1e4
commit 1dcfed86ab
52 changed files with 1695 additions and 368 deletions
@@ -133,3 +133,129 @@ test('createFieldGroupingOverlayRuntime callback restores hidden visible overlay
assert.equal(visible, false);
assert.deepEqual(visibilityTransitions, [true, false]);
});
async function settleWithinMicrotasks<T>(
promise: Promise<T>,
attempts = 10,
): Promise<T | 'timeout'> {
let settled = false;
let settledValue: T | undefined;
void promise.then((value) => {
settled = true;
settledValue = value;
});
for (let i = 0; i < attempts; i += 1) {
await Promise.resolve();
if (settled) {
return settledValue as T;
}
}
return 'timeout';
}
test('createFieldGroupingOverlayRuntime callback cancels and cleans up when kiku modal never acknowledges open', async () => {
let resolver: ((choice: KikuFieldGroupingChoice) => void) | null = null;
const sends: Array<{
channel: string;
payload: unknown;
restoreOnModalClose?: string;
preferModalWindow?: boolean;
}> = [];
const waitCalls: Array<{ modal: string; timeoutMs: number }> = [];
const warnings: string[] = [];
const closed: string[] = [];
const originalSetTimeout = globalThis.setTimeout;
globalThis.setTimeout = (() => 0) as unknown as typeof globalThis.setTimeout;
try {
const runtime = createFieldGroupingOverlayRuntime<'kiku'>({
getMainWindow: () => null,
getVisibleOverlayVisible: () => true,
setVisibleOverlayVisible: () => {},
getResolver: () => resolver,
setResolver: (nextResolver) => {
resolver = nextResolver;
},
getRestoreVisibleOverlayOnModalClose: () => new Set<'kiku'>(),
sendToVisibleOverlay: (channel, payload, runtimeOptions) => {
sends.push({
channel,
payload,
restoreOnModalClose: runtimeOptions?.restoreOnModalClose,
preferModalWindow: runtimeOptions?.preferModalWindow,
});
return true;
},
waitForModalOpen: async (modal, timeoutMs) => {
waitCalls.push({ modal, timeoutMs });
return false;
},
handleOverlayModalClosed: (modal) => {
closed.push(modal);
},
logWarn: (message) => {
warnings.push(message);
},
});
const request = {
original: {
noteId: 1,
expression: 'a',
sentencePreview: 'a',
hasAudio: false,
hasImage: false,
isOriginal: true,
},
duplicate: {
noteId: 2,
expression: 'b',
sentencePreview: 'b',
hasAudio: false,
hasImage: false,
isOriginal: false,
},
};
const pendingChoice = runtime.createFieldGroupingCallback()(request);
const result = await settleWithinMicrotasks(pendingChoice);
assert.notEqual(result, 'timeout');
assert.deepEqual(result, {
keepNoteId: 0,
deleteNoteId: 0,
deleteDuplicate: true,
cancelled: true,
});
assert.equal(resolver, null);
assert.deepEqual(
sends.map(({ channel, restoreOnModalClose, preferModalWindow }) => ({
channel,
restoreOnModalClose,
preferModalWindow,
})),
[
{
channel: 'kiku:field-grouping-request',
restoreOnModalClose: 'kiku',
preferModalWindow: true,
},
{
channel: 'kiku:field-grouping-request',
restoreOnModalClose: 'kiku',
preferModalWindow: true,
},
],
);
assert.deepEqual(waitCalls, [
{ modal: 'kiku', timeoutMs: 1500 },
{ modal: 'kiku', timeoutMs: 1500 },
]);
assert.deepEqual(warnings, [
'Kiku field grouping modal did not acknowledge modal open on first attempt; retrying dedicated modal window.',
]);
assert.deepEqual(closed, ['kiku']);
} finally {
globalThis.setTimeout = originalSetTimeout;
}
});