Refactor test database setup and add migrations

- Updated test files to use a separate test database configuration.
- Introduced a new helper module for managing test database operations.
- Added a setup file to configure the environment for tests.
- Created new database migration scripts to optimize message indexing.
- Added a sample environment file for test database configuration.
This commit is contained in:
MythEclipse
2026-05-31 16:32:38 +07:00
parent 8a712cff9b
commit f224be2a66
16 changed files with 1639 additions and 70 deletions
+22 -12
View File
@@ -686,9 +686,7 @@ describe("runModerationAnalysis", () => {
expect(secondRequestBody.messages[0].content).toContain(
"RESPON SEBELUMNYA GAGAL VALIDASI",
);
expect(secondRequestBody.messages[0].content).toContain(
"Invalid option",
);
expect(secondRequestBody.messages[0].content).toContain("Invalid option");
expect(secondRequestBody.messages[0].content).toContain(
"Coba lagi dengan output JSON yang benar",
);
@@ -753,8 +751,8 @@ describe("runModerationAnalysis", () => {
arrayBuffer: async () => {
// Minimal valid PNG bytes (8-byte signature)
const png = Buffer.from([
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00,
0x0d, 0x49, 0x48, 0x44, 0x52,
]);
return png.buffer.slice(
png.byteOffset,
@@ -932,7 +930,8 @@ describe("runModerationAnalysis", () => {
status: "warn",
flags: ["harassment"],
score: 0.65,
analysis: "Teks mengandung unsur harassment dan memerlukan tindakan lebih lanjut.",
analysis:
"Teks mengandung unsur harassment dan memerlukan tindakan lebih lanjut.",
},
],
}),
@@ -941,7 +940,22 @@ describe("runModerationAnalysis", () => {
],
};
const imageBytes = Buffer.from("realistic-image-bytes");
const imageBytes = Buffer.from([
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
]);
const toBody = (buffer: Buffer) => {
let done = false;
return {
getReader: () => ({
read: async () => {
if (done) return { done: true, value: undefined };
done = true;
return { done: false, value: new Uint8Array(buffer) };
},
cancel: vi.fn(),
}),
};
};
global.fetch = vi.fn().mockImplementation((url: string) => {
if (
url === "https://httpbin.org/image/png" ||
@@ -949,11 +963,7 @@ describe("runModerationAnalysis", () => {
) {
return Promise.resolve({
ok: true,
arrayBuffer: async () =>
imageBytes.buffer.slice(
imageBytes.byteOffset,
imageBytes.byteOffset + imageBytes.byteLength,
),
body: toBody(imageBytes),
});
}
+7 -16
View File
@@ -7,11 +7,12 @@ import {
it,
vi,
} from "vitest";
import { closeDatabase } from "../../src/database/drizzle";
import {
closeDatabase,
getDatabase,
initializeDatabase,
} from "../../src/database/drizzle";
clearTestTables,
getTestDatabase,
initializeTestDatabase,
} from "../helpers/testDatabase";
import { captureMessage } from "../../src/moderation/messageCapture";
import type { ModerationBroadcaster } from "../../src/moderation/types";
@@ -22,14 +23,6 @@ type ModerationTestGlobal = typeof globalThis & {
moderationBroadcaster?: Partial<ModerationBroadcaster>;
};
interface TestDatabase {
run(sql: string): Promise<unknown>;
}
function getTestDatabase(): TestDatabase {
return getDatabase() as unknown as TestDatabase;
}
vi.mock("../../src/moderation/aiAnalyzer", () => ({
queueMessageAnalysis: (id: string) => queueMessageAnalysis(id),
}));
@@ -118,15 +111,13 @@ async function createTables() {
describe("captureMessage", () => {
beforeAll(async () => {
await initializeDatabase();
await initializeTestDatabase();
await createTables();
});
beforeEach(async () => {
queueMessageAnalysis.mockClear();
const db = getTestDatabase();
await db.run(`DELETE FROM "attachments"`);
await db.run(`DELETE FROM "messages"`);
await clearTestTables("attachments", "messages");
delete (globalThis as ModerationTestGlobal).moderationBroadcaster;
});
+7 -16
View File
@@ -1,9 +1,10 @@
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
import { closeDatabase } from "../../src/database/drizzle";
import {
closeDatabase,
getDatabase,
initializeDatabase,
} from "../../src/database/drizzle";
clearTestTables,
getTestDatabase,
initializeTestDatabase,
} from "../helpers/testDatabase";
import { createChildLogger } from "../../src/logger";
import {
decodeCursor,
@@ -18,14 +19,6 @@ import {
} from "../../src/moderation/messageStore";
import type { MessageRecord } from "../../src/moderation/types";
interface TestDatabase {
run(sql: string): Promise<unknown>;
}
function getTestDatabase(): TestDatabase {
return getDatabase() as unknown as TestDatabase;
}
const logger = createChildLogger("messageStoreQueries.test");
describe("message cursor helpers", () => {
@@ -44,7 +37,7 @@ describe("message cursor helpers", () => {
describe("message query integration tests", () => {
beforeAll(async () => {
await initializeDatabase();
await initializeTestDatabase();
// Create tables directly for isolated query integration tests
const db = getTestDatabase();
try {
@@ -110,9 +103,7 @@ describe("message query integration tests", () => {
beforeEach(async () => {
// Clear tables before each test
try {
const db = getTestDatabase();
await db.run(`DELETE FROM "attachments"`);
await db.run(`DELETE FROM "messages"`);
await clearTestTables("attachments", "messages");
} catch (error) {
logger.debug({ error }, "Could not clear tables");
}