test: made tests work in windows

This commit is contained in:
Simeon Radivoev 2026-03-31 04:44:42 +03:00
parent 8a0be8c913
commit 4271f268c3
Signed by: simeonradivoev
GPG key ID: 7611A451D2A5D37A
9 changed files with 57 additions and 20 deletions

View file

@ -41,8 +41,8 @@ export let taskQueue: TaskQueue;
export let plugins: PluginManager; export let plugins: PluginManager;
export let events: EventEmitter<AppEventMap>; export let events: EventEmitter<AppEventMap>;
let controlsHandle: { cleanup: () => void; }; let controlsHandle: { cleanup: () => void; };
let api: any; let api: { cleanup: () => Promise<void>; };
let bunServer: { stop: () => void; } | undefined; let bunServer: { cleanup: () => Promise<void>; } | undefined;
export async function load () export async function load ()
{ {
@ -97,13 +97,16 @@ export async function load ()
export async function cleanup () export async function cleanup ()
{ {
console.log("Cleaning Up"); console.log("Cleaning Up");
bunServer?.stop(); await bunServer?.cleanup();
await api.apiServer.stop(true);
await api.cleanup(); await api.cleanup();
await taskQueue.close(); await taskQueue.close();
await plugins.cleanup();
controlsHandle.cleanup(); controlsHandle.cleanup();
sqlite.close(); cacheSqlite.close();
emulatorsSqlite.close(); emulatorsSqlite.close();
sqlite.close();
config._closeWatcher();
customEmulators._closeWatcher();
console.log("Finished Cleaning Up"); console.log("Finished Cleaning Up");
} }
@ -117,7 +120,7 @@ export async function reloadDatabase ()
db = drizzle(sqlite, { schema }); db = drizzle(sqlite, { schema });
cache = drizzle(cacheSqlite, { schema: cacheSchema }); cache = drizzle(cacheSqlite, { schema: cacheSchema });
migrate(db!, { migrationsFolder: appPath("./drizzle") }); migrate(db!, { migrationsFolder: appPath("./drizzle") });
cache.run(` await cache.run(`
CREATE TABLE IF NOT EXISTS item_cache ( CREATE TABLE IF NOT EXISTS item_cache (
key TEXT PRIMARY KEY, key TEXT PRIMARY KEY,
data TEXT NOT NULL, data TEXT NOT NULL,

View file

@ -11,6 +11,7 @@ import fs from "node:fs/promises";
import { Downloader } from "@/bun/utils/downloader"; import { Downloader } from "@/bun/utils/downloader";
import { ensureDir, move } from "fs-extra"; import { ensureDir, move } from "fs-extra";
import { simulateProgress } from "@/bun/utils"; import { simulateProgress } from "@/bun/utils";
import { path7za } from "7zip-bin";
type EmulatorDownloadStates = "download" | "extract"; type EmulatorDownloadStates = "download" | "extract";
@ -97,7 +98,7 @@ export class EmulatorDownloadJob implements IJob<z.infer<typeof EmulatorDownload
let destinationPath = destinationPaths[0]; let destinationPath = destinationPaths[0];
await new Promise((resolve, reject) => await new Promise((resolve, reject) =>
{ {
const seven = Seven.extractFull(destinationPath, emulatorsFolder, { $bin: process.env.ZIP7_PATH, $progress: true }); const seven = Seven.extractFull(destinationPath, emulatorsFolder, { $bin: process.env.ZIP7_PATH ?? path7za, $progress: true, noRootDuplication: true });
seven.on('progress', p => context.setProgress(p.percent, "extract")); seven.on('progress', p => context.setProgress(p.percent, "extract"));
seven.on('error', e => reject(e)); seven.on('error', e => reject(e));
seven.on('end', () => resolve(true)); seven.on('end', () => resolve(true));

View file

@ -14,6 +14,7 @@ import Seven from 'node-7z';
import z from "zod"; import z from "zod";
import { checkFiles } from "../games/services/utils"; import { checkFiles } from "../games/services/utils";
import { ensureDir } from "fs-extra"; import { ensureDir } from "fs-extra";
import { path7za } from "7zip-bin";
interface JobConfig interface JobConfig
{ {
@ -45,7 +46,7 @@ export class InstallJob implements IJob<never, InstallJobStates>
public async start (cx: JobContext<InstallJob, never, InstallJobStates>) public async start (cx: JobContext<InstallJob, never, InstallJobStates>)
{ {
cx.setProgress(0, 'download'); cx.setProgress(0, 'download');
fs.mkdir(config.get('downloadPath'), { recursive: true }); await fs.mkdir(config.get('downloadPath'), { recursive: true });
const downloadPath = config.get('downloadPath'); const downloadPath = config.get('downloadPath');
let info: DownloadInfo | undefined; let info: DownloadInfo | undefined;
@ -111,7 +112,7 @@ export class InstallJob implements IJob<never, InstallJobStates>
const extractPath = path.join(config.get('downloadPath'), info.extract_path); const extractPath = path.join(config.get('downloadPath'), info.extract_path);
await new Promise((resolve, reject) => await new Promise((resolve, reject) =>
{ {
const seven = Seven.extractFull(filePath, extractPath, { $bin: process.env.ZIP7_PATH, $progress: true }); const seven = Seven.extractFull(filePath, extractPath, { $bin: process.env.ZIP7_PATH ?? path7za, $progress: true });
seven.on('progress', p => seven.on('progress', p =>
{ {
cx.setProgress(progress + p.percent * progressDelta, "extract"); cx.setProgress(progress + p.percent * progressDelta, "extract");

View file

@ -42,7 +42,7 @@ export async function RunAPIServer ()
apiServer: api, apiServer: api,
async cleanup () async cleanup ()
{ {
await api.stop(); await api.stop(true);
} }
}; };
} }

View file

@ -105,7 +105,7 @@ export class TaskQueue
{ {
this.queue = []; this.queue = [];
this.activeQueue.forEach(c => c.abort()); this.activeQueue.forEach(c => c.abort());
return Promise.all(this.activeQueue.map(c => c.promise)); return Promise.all(this.activeQueue.map(c => c.promise.promise));
} }
} }

View file

@ -4,7 +4,7 @@ import { appPath } from "./utils";
import Elysia from "elysia"; import Elysia from "elysia";
import cors from "@elysiajs/cors"; import cors from "@elysiajs/cors";
export function RunBunServer () export async function RunBunServer ()
{ {
console.log("Launching Server on port ", SERVER_PORT); console.log("Launching Server on port ", SERVER_PORT);
const server = new Elysia() const server = new Elysia()
@ -24,11 +24,21 @@ export function RunBunServer ()
}) })
.get("/*", ({ params }) => Bun.file(appPath(`./dist/${params["*"]}`))); .get("/*", ({ params }) => Bun.file(appPath(`./dist/${params["*"]}`)));
return new Promise<typeof server>((resolve) =>
await new Promise<typeof server>((resolve) =>
{ {
server.listen({ port: SERVER_PORT, hostname: host, development: true }, async ({ hostname, port }) => server.listen({ port: SERVER_PORT, hostname: host, development: true }, async ({ hostname, port }) =>
{ {
resolve(server); resolve(server);
}); });
}); });
await server.modules;
return {
cleanup: async () =>
{
await server.stop(true);
}
};
} }

View file

@ -191,6 +191,7 @@ export class Downloader
return; return;
} }
reader.cancel();
console.log("Aborting Download: ", this.signal.reason); console.log("Aborting Download: ", this.signal.reason);
break; break;
} }
@ -203,7 +204,8 @@ export class Downloader
await new Promise((resolve, reject) => await new Promise((resolve, reject) =>
{ {
stream.end(() => resolve(undefined)); stream.end();
stream.on("close", () => resolve(false));
stream.on("error", reject); stream.on("error", reject);
}); });
} }

View file

@ -136,6 +136,12 @@ describe("Download Tests", () =>
type: "direct", type: "direct",
url: `${server.url.href}download/zip_file_with_single_file.zip?root=test` url: `${server.url.href}download/zip_file_with_single_file.zip?root=test`
} }
],
"win32:x64": [
{
type: "direct",
url: `${server.url.href}download/zip_file_with_single_file.zip?root=test`
}
] ]
}, },
keywords: [ keywords: [

View file

@ -2,6 +2,7 @@ import { afterAll, beforeAll, beforeEach, afterEach } from 'bun:test';
import { resolve } from 'node:path'; import { resolve } from 'node:path';
import * as app from '@/bun/api/app'; import * as app from '@/bun/api/app';
import { remove } from 'fs-extra'; import { remove } from 'fs-extra';
import { spawnSync } from "child_process";
export async function LoadApp () export async function LoadApp ()
{ {
@ -12,7 +13,7 @@ export async function LoadApp ()
export async function CleanupApp () export async function CleanupApp ()
{ {
console.log("Cleaning Up App"); console.log("Cleaning Up App");
app.cleanup(); await app.cleanup();
} }
beforeAll(async () => beforeAll(async () =>
@ -22,12 +23,25 @@ beforeAll(async () =>
process.env.DEFAULT_DOWNLOAD_PATH = resolve('./src/tests/mock-roms'); process.env.DEFAULT_DOWNLOAD_PATH = resolve('./src/tests/mock-roms');
}); });
async function FileCleanup ()
{
try
{
await remove(resolve('./src/tests/mock-config'));
await remove(resolve('./src/tests/mock-store'));
await remove(resolve('./src/tests/mock-roms'));
} catch
{
//TODO: Bun doesn't close DB correctly and it gets locked so it doesn't get removed
}
}
beforeEach(FileCleanup);
afterEach(async () => afterEach(async () =>
{ {
await remove(resolve('./src/tests/mock-config')); await CleanupApp();
await remove(resolve('./src/tests/mock-roms')); await FileCleanup();
await remove(resolve('./src/tests/mock-store'));
}); });
beforeEach(LoadApp, { timeout: 30000 }); beforeEach(LoadApp);
afterEach(CleanupApp);