fix(dictionary): complete Hachidori imports and mining integration

This commit is contained in:
2026-09-22 15:01:23 -07:00
parent 15c74ef502
commit ab5e50adac
44 changed files with 756 additions and 40 deletions
+16 -5
View File
@@ -7,7 +7,11 @@ if (process.platform !== 'linux')
throw new Error('This app-entry smoke requires Linux XDG isolation.');
const root = process.cwd();
const backend = process.argv.includes('--backend=yomitan') ? 'yomitan' : 'hachidori';
const profile = fs.mkdtempSync('/tmp/subminer-hachi-settings-');
const profile = process.env.SUBMINER_DICTIONARY_SMOKE_DATA;
assert(
profile && fs.existsSync(profile),
'Use bun run test:dictionary:electron for profile isolation',
);
process.env.XDG_CONFIG_HOME = profile;
process.env.XDG_DATA_HOME = path.join(profile, 'data');
fs.mkdirSync(path.join(profile, 'SubMiner'));
@@ -15,6 +19,10 @@ fs.writeFileSync(
path.join(profile, 'SubMiner', 'config.json'),
JSON.stringify({
dictionaryBackend: backend,
// An inactive external Yomitan profile must not block bundled settings in Hachidori mode.
yomitan: {
externalProfilePath: backend === 'hachidori' ? path.join(profile, 'external-yomitan') : '',
},
mpv: { socketPath: path.join(profile, 'missing-mpv.sock') },
ankiConnect: { enabled: false },
startupWarmups: { lowPowerMode: true },
@@ -39,8 +47,12 @@ const deadline = setTimeout(() => {
'FAIL timeout',
BrowserWindow.getAllWindows().map((w) => w.webContents.getURL()),
);
app.exit(1);
finish(1);
}, 60000);
function finish(exitCode) {
clearTimeout(deadline);
app.exit(exitCode);
}
(async () => {
await app.whenReady();
let window;
@@ -102,9 +114,8 @@ const deadline = setTimeout(() => {
`PASS ${backend} overlay session, independent settings windows, real preload external link bridge`,
);
clearTimeout(deadline);
app.exit(0);
finish(0);
})().catch((error) => {
console.error(error);
app.exit(1);
finish(1);
});
+26
View File
@@ -0,0 +1,26 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
const require = createRequire(import.meta.url);
const profile = fs.mkdtempSync(path.join(os.tmpdir(), 'subminer-hachi-settings-'));
const env = { ...process.env, SUBMINER_DICTIONARY_SMOKE_DATA: profile };
delete env.ELECTRON_RUN_AS_NODE;
try {
const result = spawnSync(
require('electron'),
[
'--no-sandbox',
fileURLToPath(new URL('./check-dictionary-backends.cjs', import.meta.url)),
...process.argv.slice(2),
],
{ env, stdio: 'inherit', timeout: 75_000 },
);
if (result.error) throw result.error;
process.exitCode = result.status ?? 1;
} finally {
fs.rmSync(profile, { recursive: true, force: true, maxRetries: 3 });
}
+5 -1
View File
@@ -99,7 +99,11 @@ async function smoke() {
if (details.statusCode >= 400) failedRequests.push(`${details.url}: ${details.statusCode}`);
});
await statsWindow.loadURL(url);
assert.equal((await fetch(`${url}/api/stats/overview`)).status, 200);
for (const endpoint of ['overview', 'sessions']) {
const response = await fetch(`${url}/api/stats/${endpoint}`);
assert.equal(response.status, 200, `Stats ${endpoint} request failed`);
await response.json();
}
} finally {
statsWindow.destroy();
await statsServer.close();