feat(config): add configuration window (#70)

This commit is contained in:
2026-05-21 04:16:21 -07:00
committed by GitHub
parent a54f03f0cd
commit dc52bc2fba
287 changed files with 14507 additions and 8134 deletions
@@ -114,3 +114,83 @@ test('yomitan extension runtime direct load delegates to core', async () => {
assert.equal(receivedExternalProfilePath, '/tmp/gsm-profile');
assert.deepEqual(yomitanSession, { id: 'session' });
});
test('yomitan extension runtime notifies once after concurrent ensure load resolves', async () => {
let extension: Extension | null = null;
let inFlight: Promise<Extension | null> | null = null;
const notifications: Extension[] = [];
const releaseLoadState: { releaseLoad: ((value: Extension | null) => void) | null } = {
releaseLoad: null,
};
const runtime = createYomitanExtensionRuntime({
loadYomitanExtensionCore: async (options) => {
return await new Promise<Extension | null>((resolve) => {
releaseLoadState.releaseLoad = (value) => {
options.setYomitanExtension(value);
resolve(value);
};
});
},
userDataPath: '/tmp',
getYomitanParserWindow: () => null,
setYomitanParserWindow: () => {},
setYomitanParserReadyPromise: () => {},
setYomitanParserInitPromise: () => {},
setYomitanExtension: (next) => {
extension = next;
},
setYomitanSession: () => {},
getYomitanExtension: () => extension,
getLoadInFlight: () => inFlight,
setLoadInFlight: (promise) => {
inFlight = promise;
},
onYomitanExtensionLoaded: (loadedExtension) => {
notifications.push(loadedExtension);
},
});
const first = runtime.ensureYomitanExtensionLoaded();
const second = runtime.ensureYomitanExtensionLoaded();
const fakeExtension = { id: 'yomitan' } as Extension;
const releaseLoad = releaseLoadState.releaseLoad;
if (!releaseLoad) {
throw new Error('expected in-flight yomitan load resolver');
}
releaseLoad(fakeExtension);
assert.equal(await first, fakeExtension);
assert.equal(await second, fakeExtension);
assert.deepEqual(notifications, [fakeExtension]);
});
test('yomitan extension runtime retries notification after callback failure', async () => {
const fakeExtension = { id: 'yomitan' } as Extension;
let calls = 0;
const runtime = createYomitanExtensionRuntime({
loadYomitanExtensionCore: async () => fakeExtension,
userDataPath: '/tmp',
getYomitanParserWindow: () => null,
setYomitanParserWindow: () => {},
setYomitanParserReadyPromise: () => {},
setYomitanParserInitPromise: () => {},
setYomitanExtension: () => {},
setYomitanSession: () => {},
getYomitanExtension: () => fakeExtension,
getLoadInFlight: () => null,
setLoadInFlight: () => {},
onYomitanExtensionLoaded: () => {
calls += 1;
if (calls === 1) {
throw new Error('overlay reload failed');
}
},
});
await assert.rejects(runtime.ensureYomitanExtensionLoaded(), /overlay reload failed/);
assert.equal(await runtime.ensureYomitanExtensionLoaded(), fakeExtension);
assert.equal(calls, 2);
});