Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions server/claim/parser/parser.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Test, TestingModule } from "@nestjs/testing";
import { ParserService } from "./parser.service";
import * as fs from "fs";
import { TestConfigOptions } from "../../tests/utils/TestConfigOptions";
import { MongoMemoryServer } from "mongodb-memory-server";
import { Types } from "mongoose";
import { AppModule } from "../../app.module";
import { SessionGuard } from "../../auth/session.guard";
Expand All @@ -11,6 +10,7 @@ import { SessionOrM2MGuard } from "../../auth/m2m-or-session.guard";
import { SessionOrM2MGuardMock } from "../../tests/mocks/SessionOrM2MGuardMock";
import { M2MGuard } from "../../auth/m2m.guard";
import { M2MGuardMock } from "../../tests/mocks/M2MGuardMock";
import { CleanupDatabase } from "../../tests/utils/CleanupDatabase";

/**
* ParserService Unit Test Suite
Expand All @@ -36,13 +36,12 @@ import { M2MGuardMock } from "../../tests/mocks/M2MGuardMock";
*/
describe("ParserService", () => {
let parserService: ParserService;
let db: any;
let moduleFixture: TestingModule;
const claimRevisionIdMock = new Types.ObjectId();

beforeAll(async () => {
db = await MongoMemoryServer.create({ instance: { port: 35025 } });
const mongoUri = db.getUri();
// Use shared MongoDB instance from global setup
const mongoUri = process.env.MONGO_URI!;

// Update the test config with the actual MongoDB URI
const testConfig = {
Expand Down Expand Up @@ -277,8 +276,6 @@ describe("ParserService", () => {
});

afterAll(async () => {
if (db) {
await db.stop();
}
await CleanupDatabase(process.env.MONGO_URI!);
});
});
13 changes: 6 additions & 7 deletions server/tests/claim-review.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MongoMemoryServer } from "mongodb-memory-server";
import * as request from "supertest";
import { Test, TestingModule } from "@nestjs/testing";
import { AppModule } from "../app.module";
Expand All @@ -24,6 +23,7 @@ import { SeedTestSpeech } from "./utils/SeedTestSpeech";
import { SeedTestClaimRevision } from "./utils/SeedTestClaimRevision";
import { SeedTestClaim } from "./utils/SeedTestClaim";
import { ValidationPipe } from "@nestjs/common";
import { CleanupDatabase } from "./utils/CleanupDatabase";
const { ObjectId } = require("mongodb");

jest.setTimeout(10000);
Expand All @@ -45,7 +45,6 @@ jest.setTimeout(10000);
*/
describe("ClaimReviewController (e2e)", () => {
let app: any;
let db: any;
let userId: string;
let personalitiesId: string[];
let reportId: string;
Expand All @@ -57,8 +56,8 @@ describe("ClaimReviewController (e2e)", () => {
let claimReviewId: string;

beforeAll(async () => {
db = await MongoMemoryServer.create({ instance: { port: 35025 } });
const mongoUri = db.getUri();
// Use shared MongoDB instance from global setup
const mongoUri = process.env.MONGO_URI!;

const user = await SeedTestUser(mongoUri);
userId = user.insertedId.toString();
Expand Down Expand Up @@ -346,7 +345,7 @@ describe("ClaimReviewController (e2e)", () => {
it("api/review/:id (PUT) - Should validate update payload", () => {
// First create a new review for this test by re-seeding
return SeedTestClaimReview(
db.getUri(),
process.env.MONGO_URI!,
claimId,
personalitiesId,
reportId,
Expand Down Expand Up @@ -385,7 +384,7 @@ describe("ClaimReviewController (e2e)", () => {
});

afterAll(async () => {
await db.stop();
app.close();
await app.close();
await CleanupDatabase(process.env.MONGO_URI!);
});
});
15 changes: 7 additions & 8 deletions server/tests/claim.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MongoMemoryServer } from "mongodb-memory-server";
import * as request from "supertest";
import { Test, TestingModule } from "@nestjs/testing";
import { ValidationPipe } from "@nestjs/common";
Expand All @@ -20,6 +19,7 @@ import { CaptchaService } from "../captcha/captcha.service";
import { MongoPersonalityService } from "../personality/mongo/personality.service";
import { HistoryService } from "../history/history.service";
import { HistoryServiceMock } from "./mocks/HistoryServiceMock";
import { CleanupDatabase } from "./utils/CleanupDatabase";

jest.setTimeout(10000);

Expand Down Expand Up @@ -79,7 +79,6 @@ const personalityService = {

describe("ClaimController (e2e)", () => {
let app: any;
let db: any;
let personalitiesId: string[];
let claimId: string;
let speechClaimId: string;
Expand All @@ -92,14 +91,14 @@ describe("ClaimController (e2e)", () => {
const date: string = "2023-11-25T14:49:30.992Z";

beforeAll(async () => {
db = await MongoMemoryServer.create({ instance: { port: 35025 } });
const mongoUri = db.getUri();
// Use shared MongoDB instance from global setup
const mongoUri = process.env.MONGO_URI!;

await SeedTestUser(mongoUri);
const { insertedIds } = await SeedTestPersonality(mongoUri);
personalitiesId = [insertedIds["0"].toString(), insertedIds["1"].toString()];

// Update test config with actual MongoDB URI
// Update test config with shared MongoDB URI
const testConfig = {
...TestConfigOptions.config,
db: {
Expand Down Expand Up @@ -599,7 +598,7 @@ describe("ClaimController (e2e)", () => {
});

afterAll(async () => {
await db.stop();
app.close();
await app.close();
await CleanupDatabase(process.env.MONGO_URI!);
});
});
22 changes: 22 additions & 0 deletions server/tests/globalSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { MongoMemoryServer } from "mongodb-memory-server";

/**
* Global setup for Jest test suite
* Creates a shared MongoMemoryServer instance for all test suites
* to improve performance and reduce resource usage
*/
export default async function globalSetup() {
const instance = await MongoMemoryServer.create({
instance: {
dbName: "jest-test",
},
});

const uri = instance.getUri();

// Store instance globally for teardown
(global as any).__MONGOINSTANCE = instance;

// Store URI in environment for all tests to use
process.env.MONGO_URI = uri;
}
11 changes: 11 additions & 0 deletions server/tests/globalTeardown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Global teardown for Jest test suite
* Stops the shared MongoMemoryServer instance created in globalSetup
*/
export default async function globalTeardown() {
const instance = (global as any).__MONGOINSTANCE;

if (instance) {
await instance.stop();
}
}
6 changes: 5 additions & 1 deletion server/tests/jest-e2e.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,9 @@
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"modulePathIgnorePatterns": ["./dist/"]
"modulePathIgnorePatterns": ["./dist/"],
"globalSetup": "./globalSetup.ts",
"globalTeardown": "./globalTeardown.ts",
"maxWorkers": "50%",
"testTimeout": 30000
}
11 changes: 5 additions & 6 deletions server/tests/notification.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MongoMemoryServer } from "mongodb-memory-server";
import * as request from "supertest";
import { Test, TestingModule } from "@nestjs/testing";
import { ValidationPipe } from "@nestjs/common";
Expand All @@ -15,6 +14,7 @@ import { AbilitiesGuard } from "../auth/ability/abilities.guard";
import { AbilitiesGuardMock } from "./mocks/AbilitiesGuardMock";
import { AdminUserMock } from "./utils/AdminUserMock";
import { NotificationService } from "../notifications/notifications.service";
import { CleanupDatabase } from "./utils/CleanupDatabase";

jest.setTimeout(10000);

Expand Down Expand Up @@ -45,12 +45,11 @@ const notificationService = {

describe("NotificationController (e2e)", () => {
let app: any;
let db: any;
const payload = "Test Message Notification";

beforeAll(async () => {
db = await MongoMemoryServer.create({ instance: { port: 35025 } });
const mongoUri = db.getUri();
// Use shared MongoDB instance from global setup
const mongoUri = process.env.MONGO_URI!;

await SeedTestUser(mongoUri);

Expand Down Expand Up @@ -245,7 +244,7 @@ describe("NotificationController (e2e)", () => {

afterAll(async () => {
jest.restoreAllMocks();
await db.stop();
app.close();
await app.close();
await CleanupDatabase(process.env.MONGO_URI!);
});
});
11 changes: 5 additions & 6 deletions server/tests/personality.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MongoMemoryServer } from "mongodb-memory-server";
import * as request from "supertest";
import { Test, TestingModule } from "@nestjs/testing";
import { ValidationPipe } from "@nestjs/common";
Expand All @@ -15,6 +14,7 @@ import { AbilitiesGuard } from "../auth/ability/abilities.guard";
import { AbilitiesGuardMock } from "./mocks/AbilitiesGuardMock";
import { HistoryService } from "../history/history.service";
import { HistoryServiceMock } from "./mocks/HistoryServiceMock";
import { CleanupDatabase } from "./utils/CleanupDatabase";

jest.setTimeout(10000);

Expand All @@ -40,12 +40,11 @@ jest.setTimeout(10000);
*/
describe("PersonalityController (e2e)", () => {
let app: any;
let db: any;
let personalityId: string;

beforeAll(async () => {
db = await MongoMemoryServer.create({ instance: { port: 35025 } });
const mongoUri = db.getUri();
// Use shared MongoDB instance from global setup
const mongoUri = process.env.MONGO_URI!;

await SeedTestUser(mongoUri);

Expand Down Expand Up @@ -408,7 +407,7 @@ describe("PersonalityController (e2e)", () => {
});

afterAll(async () => {
await db.stop();
app.close();
await app.close();
await CleanupDatabase(process.env.MONGO_URI!);
});
});
11 changes: 5 additions & 6 deletions server/tests/source.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { MongoMemoryServer } from "mongodb-memory-server";
import * as request from "supertest";
import { Test, TestingModule } from "@nestjs/testing";
import { ValidationPipe } from "@nestjs/common";
Expand All @@ -18,6 +17,7 @@ import { HistoryServiceMock } from "./mocks/HistoryServiceMock";
import { NameSpaceEnum } from "../auth/name-space/schemas/name-space.schema";
import { SeedTestPersonality } from "./utils/SeedTestPersonality";
import { SeedTestClaim } from "./utils/SeedTestClaim";
import { CleanupDatabase } from "./utils/CleanupDatabase";
const { ObjectId } = require("mongodb");

jest.setTimeout(10000);
Expand Down Expand Up @@ -45,15 +45,14 @@ jest.setTimeout(10000);
*/
describe("SourceController (e2e)", () => {
let app: any;
let db: any;
let userId: string;
let personalitiesId: string[];
let claimId: string;
let targetId: string;

beforeAll(async () => {
db = await MongoMemoryServer.create({ instance: { port: 35025 } });
const mongoUri = db.getUri();
// Use shared MongoDB instance from global setup
const mongoUri = process.env.MONGO_URI!;

const user = await SeedTestUser(mongoUri);
userId = user.insertedId.toString();
Expand Down Expand Up @@ -368,7 +367,7 @@ describe("SourceController (e2e)", () => {

afterAll(async () => {
jest.restoreAllMocks();
await db.stop();
app.close();
await app.close();
await CleanupDatabase(process.env.MONGO_URI!);
});
});
31 changes: 31 additions & 0 deletions server/tests/utils/CleanupDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { MongoClient } from "mongodb";
import { TEST_DB_NAME } from "./TestConstants";

/**
* Cleanup utility to clear database collections between test suites
* This prevents duplicate key errors when running tests sequentially
*
* @param mongoUri - MongoDB connection URI
* @throws Error if database cleanup fails
*/
export async function CleanupDatabase(mongoUri: string): Promise<void> {
const client = await MongoClient.connect(mongoUri);

try {
const db = client.db(TEST_DB_NAME);
const collections = await db.listCollections().toArray();

// Delete all documents from all collections to ensure clean state
for (const collection of collections) {
await db.collection(collection.name).deleteMany({});
}
} catch (error) {
throw new Error(
`Database cleanup failed for ${TEST_DB_NAME}: ${
error instanceof Error ? error.message : String(error)
}`
);
} finally {
await client.close();
}
}
38 changes: 35 additions & 3 deletions server/tests/utils/SeedTestPersonality.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,47 @@
import { MongoClient } from "mongodb";
import { PersonalitiesMock } from "./PersonalitiesMock";
import { TEST_DB_NAME } from "./TestConstants";

export const SeedTestPersonality = async (uri) => {
const client = await new MongoClient(uri);
await client.connect();

try {
return await client
.db("test")
// Use bulkWrite with upsert to avoid duplicate errors in parallel execution
const operations = PersonalitiesMock.map((personality) => ({
updateOne: {
filter: { slug: personality.slug },
update: { $set: personality },
upsert: true,
},
}));

const result = await client
.db(TEST_DB_NAME)
.collection("personalities")
.bulkWrite(operations);

// Get the inserted/updated IDs with explicit ordering for consistency
const personalities = await client
.db(TEST_DB_NAME)
.collection("personalities")
.insertMany(PersonalitiesMock);
.find({ slug: { $in: PersonalitiesMock.map((p) => p.slug) } })
.sort({ slug: 1 })
.toArray();

// Map by slug to ensure order-independent ID mapping
return {
insertedIds: PersonalitiesMock.reduce((acc, mock, index) => {
const personality = personalities.find(
(p) => p.slug === mock.slug
);
if (personality) {
acc[index.toString()] = personality._id;
}
return acc;
}, {}),
acknowledged: result.ok === 1,
};
} finally {
await client.close();
}
Expand Down
Loading
Loading