mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-10-25 07:17:23 +08:00
test: split integration tests (@fehmer) (#6807)
- **trigger** - **test: split integration tests (@fehmer)**
This commit is contained in:
parent
dd55a7257b
commit
c1a681c17f
22 changed files with 321 additions and 172 deletions
|
|
@ -1,10 +1,11 @@
|
|||
import * as Migration from "../../__migration__/testActivity";
|
||||
import * as UserTestData from "../__testData__/users";
|
||||
import * as UserDal from "../../src/dal/user";
|
||||
import * as ResultDal from "../../src/dal/result";
|
||||
import { DBResult } from "../../src/utils/result";
|
||||
import * as Migration from "../../../__migration__/testActivity";
|
||||
import * as UserTestData from "../../__testData__/users";
|
||||
import * as UserDal from "../../../src/dal/user";
|
||||
import * as ResultDal from "../../../src/dal/result";
|
||||
import { DBResult } from "../../../src/utils/result";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
describe("testActivity migration", () => {
|
||||
describeIntegration()("testActivity migration", () => {
|
||||
it("migrates users without results", async () => {
|
||||
//given
|
||||
const user1 = await UserTestData.createUser();
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import * as AdminUidsDal from "../../src/dal/admin-uids";
|
||||
import * as AdminUidsDal from "../../../src/dal/admin-uids";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
describe("AdminUidsDal", () => {
|
||||
describeIntegration()("AdminUidsDal", () => {
|
||||
describe("isAdmin", () => {
|
||||
it("should return true for existing admin user", async () => {
|
||||
//GIVEN
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import { addApeKey } from "../../src/dal/ape-keys";
|
||||
import { addApeKey } from "../../../src/dal/ape-keys";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
describe("ApeKeysDal", () => {
|
||||
describeIntegration()("ApeKeysDal", () => {
|
||||
it("should be able to add a new ape key", async () => {
|
||||
const apeKey = {
|
||||
_id: new ObjectId(),
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import * as BlacklistDal from "../../src/dal/blocklist";
|
||||
import * as BlacklistDal from "../../../src/dal/blocklist";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
describe("BlocklistDal", () => {
|
||||
describeIntegration()("BlocklistDal", () => {
|
||||
describe("add", () => {
|
||||
beforeEach(() => {
|
||||
vitest.useFakeTimers();
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
import _ from "lodash";
|
||||
import { ObjectId } from "mongodb";
|
||||
import * as UserDal from "../../src/dal/user";
|
||||
import * as LeaderboardsDal from "../../src/dal/leaderboards";
|
||||
import * as PublicDal from "../../src/dal/public";
|
||||
import * as Configuration from "../../src/init/configuration";
|
||||
import type { DBLeaderboardEntry } from "../../src/dal/leaderboards";
|
||||
import * as UserDal from "../../../src/dal/user";
|
||||
import * as LeaderboardsDal from "../../../src/dal/leaderboards";
|
||||
import * as PublicDal from "../../../src/dal/public";
|
||||
import * as Configuration from "../../../src/init/configuration";
|
||||
import type { DBLeaderboardEntry } from "../../../src/dal/leaderboards";
|
||||
import type { PersonalBest } from "@monkeytype/schemas/shared";
|
||||
const configuration = Configuration.getCachedConfiguration();
|
||||
|
||||
import * as DB from "../../src/init/db";
|
||||
import { LbPersonalBests } from "../../src/utils/pb";
|
||||
import * as DB from "../../../src/init/db";
|
||||
import { LbPersonalBests } from "../../../src/utils/pb";
|
||||
import { describeIntegration } from "..";
|
||||
import { pb } from "../../__testData__/users";
|
||||
|
||||
describe("LeaderboardsDal", () => {
|
||||
describeIntegration()("LeaderboardsDal", () => {
|
||||
describe("update", () => {
|
||||
it("should ignore unapplicable users on leaderboard", async () => {
|
||||
//GIVEN
|
||||
|
|
@ -328,24 +330,6 @@ function lbBests(pb15?: PersonalBest, pb60?: PersonalBest): LbPersonalBests {
|
|||
return result;
|
||||
}
|
||||
|
||||
export function pb(
|
||||
wpm: number,
|
||||
acc: number = 90,
|
||||
timestamp: number = 1
|
||||
): PersonalBest {
|
||||
return {
|
||||
acc,
|
||||
consistency: 100,
|
||||
difficulty: "normal",
|
||||
lazyMode: false,
|
||||
language: "english",
|
||||
punctuation: false,
|
||||
raw: wpm + 1,
|
||||
wpm,
|
||||
timestamp,
|
||||
};
|
||||
}
|
||||
|
||||
function premium(expirationDeltaSeconds: number) {
|
||||
return {
|
||||
premium: {
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
import { ObjectId } from "mongodb";
|
||||
import * as PresetDal from "../../src/dal/preset";
|
||||
import * as PresetDal from "../../../src/dal/preset";
|
||||
import _ from "lodash";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
describe("PresetDal", () => {
|
||||
describeIntegration()("PresetDal", () => {
|
||||
describe("readPreset", () => {
|
||||
it("should read", async () => {
|
||||
//GIVEN
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import * as PublicDAL from "../../src/dal/public";
|
||||
import { describeIntegration } from "..";
|
||||
import * as PublicDAL from "../../../src/dal/public";
|
||||
|
||||
describe("PublicDAL", function () {
|
||||
describeIntegration()("PublicDAL", function () {
|
||||
it("should be able to update stats", async function () {
|
||||
// checks it doesn't throw an error. the actual values are checked in another test.
|
||||
await PublicDAL.updateStats(1, 15);
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import * as ResultDal from "../../src/dal/result";
|
||||
import * as ResultDal from "../../../src/dal/result";
|
||||
import { ObjectId } from "mongodb";
|
||||
import * as UserDal from "../../src/dal/user";
|
||||
import { DBResult } from "../../src/utils/result";
|
||||
import * as UserDal from "../../../src/dal/user";
|
||||
import { DBResult } from "../../../src/utils/result";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
let uid: string;
|
||||
const timestamp = Date.now() - 60000;
|
||||
|
|
@ -62,7 +63,7 @@ async function createDummyData(
|
|||
});
|
||||
}
|
||||
}
|
||||
describe("ResultDal", () => {
|
||||
describeIntegration()("ResultDal", () => {
|
||||
beforeEach(() => {
|
||||
uid = new ObjectId().toHexString();
|
||||
});
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
import _ from "lodash";
|
||||
import * as UserDAL from "../../src/dal/user";
|
||||
import * as UserTestData from "../__testData__/users";
|
||||
import * as UserDAL from "../../../src/dal/user";
|
||||
import * as UserTestData from "../../__testData__/users";
|
||||
import { ObjectId } from "mongodb";
|
||||
import { MonkeyMail, ResultFilters } from "@monkeytype/schemas/users";
|
||||
import { PersonalBest, PersonalBests } from "@monkeytype/schemas/shared";
|
||||
import { CustomThemeColors } from "@monkeytype/schemas/configs";
|
||||
import { describeIntegration } from "..";
|
||||
|
||||
const mockPersonalBest = {
|
||||
acc: 1,
|
||||
|
|
@ -85,7 +86,7 @@ const mockResultFilter: ResultFilters = {
|
|||
|
||||
const mockDbResultFilter = { ...mockResultFilter, _id: new ObjectId() };
|
||||
|
||||
describe("UserDal", () => {
|
||||
describeIntegration()("UserDal", () => {
|
||||
it("should be able to insert users", async () => {
|
||||
// given
|
||||
const newUser = {
|
||||
5
backend/__tests__/__integration__/index.ts
Normal file
5
backend/__tests__/__integration__/index.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export const isIntegrationTest = process.env["INTEGRATION_TESTS"] === "true";
|
||||
|
||||
export function describeIntegration() {
|
||||
return describe.runIf(isIntegrationTest);
|
||||
}
|
||||
65
backend/__tests__/__integration__/setup-integration-tests.ts
Normal file
65
backend/__tests__/__integration__/setup-integration-tests.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import { Collection, Db, MongoClient, WithId } from "mongodb";
|
||||
import { afterAll, beforeAll, afterEach } from "vitest";
|
||||
import * as MongoDbMock from "vitest-mongodb";
|
||||
import { MongoDbMockConfig } from "../global-setup";
|
||||
import { isIntegrationTest } from ".";
|
||||
import { setupCommonMocks } from "../setup-common-mocks";
|
||||
|
||||
process.env["MODE"] = "dev";
|
||||
//process.env["MONGOMS_DISTRO"] = "ubuntu-22.04";
|
||||
|
||||
if (!isIntegrationTest) {
|
||||
console.error("wrong environment");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
if (!process.env["REDIS_URI"]) {
|
||||
// use mock if not set
|
||||
process.env["REDIS_URI"] = "redis://mock";
|
||||
}
|
||||
|
||||
let db: Db;
|
||||
let client: MongoClient;
|
||||
const collectionsForCleanUp = ["users"];
|
||||
|
||||
beforeAll(async () => {
|
||||
//don't add any configuration here, add to global-setup.ts instead.
|
||||
|
||||
console.log("integration setup mongo");
|
||||
await MongoDbMock.setup(MongoDbMockConfig);
|
||||
|
||||
client = new MongoClient(globalThis.__MONGO_URI__);
|
||||
await client.connect();
|
||||
db = client.db();
|
||||
|
||||
vi.mock("../../src/init/db", () => ({
|
||||
__esModule: true,
|
||||
getDb: (): Db => db,
|
||||
collection: <T>(name: string): Collection<WithId<T>> =>
|
||||
db.collection<WithId<T>>(name),
|
||||
close: () => {
|
||||
//
|
||||
},
|
||||
}));
|
||||
setupCommonMocks();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (globalThis.__MONGO_URI__) {
|
||||
await Promise.all(
|
||||
collectionsForCleanUp.map((collection) =>
|
||||
db.collection(collection).deleteMany({})
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await client?.close();
|
||||
await MongoDbMock.teardown();
|
||||
// @ts-ignore
|
||||
db = undefined;
|
||||
//@ts-ignore
|
||||
client = undefined;
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import * as DB from "../../src/init/db";
|
||||
import * as UserDAL from "../../src/dal/user";
|
||||
import { ObjectId } from "mongodb";
|
||||
import { PersonalBest } from "@monkeytype/schemas/shared";
|
||||
|
||||
export async function createUser(
|
||||
user?: Partial<UserDAL.DBUser>
|
||||
|
|
@ -24,3 +25,21 @@ export async function createUserWithoutMigration(
|
|||
|
||||
return await UserDAL.getUser(uid, "test");
|
||||
}
|
||||
|
||||
export function pb(
|
||||
wpm: number,
|
||||
acc: number = 90,
|
||||
timestamp: number = 1
|
||||
): PersonalBest {
|
||||
return {
|
||||
acc,
|
||||
consistency: 100,
|
||||
difficulty: "normal",
|
||||
lazyMode: false,
|
||||
language: "english",
|
||||
punctuation: false,
|
||||
raw: wpm + 1,
|
||||
wpm,
|
||||
timestamp,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,16 +36,18 @@ describe("Loaderboard Controller", () => {
|
|||
});
|
||||
describe("get leaderboard", () => {
|
||||
const getLeaderboardMock = vi.spyOn(LeaderboardDal, "get");
|
||||
const getLeaderboardCountMock = vi.spyOn(LeaderboardDal, "getCount");
|
||||
|
||||
beforeEach(() => {
|
||||
getLeaderboardMock.mockReset();
|
||||
getLeaderboardCountMock.mockReset();
|
||||
});
|
||||
|
||||
it("should get for english time 60", async () => {
|
||||
//GIVEN
|
||||
|
||||
const resultData = {
|
||||
count: 0,
|
||||
count: 42,
|
||||
pageSize: 50,
|
||||
entries: [
|
||||
{
|
||||
|
|
@ -78,6 +80,7 @@ describe("Loaderboard Controller", () => {
|
|||
_id: new ObjectId(),
|
||||
}));
|
||||
getLeaderboardMock.mockResolvedValue(mockData);
|
||||
getLeaderboardCountMock.mockResolvedValue(42);
|
||||
|
||||
//WHEN
|
||||
|
||||
|
|
@ -104,6 +107,7 @@ describe("Loaderboard Controller", () => {
|
|||
it("should get for english time 60 with page", async () => {
|
||||
//GIVEN
|
||||
getLeaderboardMock.mockResolvedValue([]);
|
||||
getLeaderboardCountMock.mockResolvedValue(0);
|
||||
const page = 0;
|
||||
const pageSize = 25;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import * as Configuration from "../../../src/init/configuration";
|
|||
import * as ResultDal from "../../../src/dal/result";
|
||||
import * as UserDal from "../../../src/dal/user";
|
||||
import * as LogsDal from "../../../src/dal/logs";
|
||||
import * as PublicDal from "../../../src/dal/public";
|
||||
import { ObjectId } from "mongodb";
|
||||
import {
|
||||
mockAuthenticateWithApeKey,
|
||||
|
|
@ -504,6 +505,7 @@ describe("result controller test", () => {
|
|||
it("should delete", async () => {
|
||||
//GIVEN
|
||||
mockAuth.modifyToken({ iat: Date.now() - 1000 });
|
||||
deleteAllMock.mockResolvedValue(undefined as any);
|
||||
|
||||
//WHEN
|
||||
const { body } = await mockApp
|
||||
|
|
@ -672,22 +674,34 @@ describe("result controller test", () => {
|
|||
describe("addResult", () => {
|
||||
//TODO improve test coverage for addResult
|
||||
const insertedId = new ObjectId();
|
||||
const getUserMock = vi.spyOn(UserDal, "getUser");
|
||||
const updateStreakMock = vi.spyOn(UserDal, "updateStreak");
|
||||
const checkIfTagPbMock = vi.spyOn(UserDal, "checkIfTagPb");
|
||||
const addResultMock = vi.spyOn(ResultDal, "addResult");
|
||||
const userGetMock = vi.spyOn(UserDal, "getUser");
|
||||
const userUpdateStreakMock = vi.spyOn(UserDal, "updateStreak");
|
||||
const userCheckIfTagPbMock = vi.spyOn(UserDal, "checkIfTagPb");
|
||||
const userCheckIfPbMock = vi.spyOn(UserDal, "checkIfPb");
|
||||
const userIncrementXpMock = vi.spyOn(UserDal, "incrementXp");
|
||||
const userUpdateTypingStatsMock = vi.spyOn(UserDal, "updateTypingStats");
|
||||
const resultAddMock = vi.spyOn(ResultDal, "addResult");
|
||||
const publicUpdateStatsMock = vi.spyOn(PublicDal, "updateStats");
|
||||
|
||||
beforeEach(async () => {
|
||||
await enableResultsSaving(true);
|
||||
|
||||
[getUserMock, updateStreakMock, checkIfTagPbMock, addResultMock].forEach(
|
||||
(it) => it.mockReset()
|
||||
);
|
||||
[
|
||||
userGetMock,
|
||||
userUpdateStreakMock,
|
||||
userCheckIfTagPbMock,
|
||||
userCheckIfPbMock,
|
||||
userIncrementXpMock,
|
||||
userUpdateTypingStatsMock,
|
||||
resultAddMock,
|
||||
publicUpdateStatsMock,
|
||||
].forEach((it) => it.mockReset());
|
||||
|
||||
getUserMock.mockResolvedValue({ name: "bob" } as any);
|
||||
updateStreakMock.mockResolvedValue(0);
|
||||
checkIfTagPbMock.mockResolvedValue([]);
|
||||
addResultMock.mockResolvedValue({ insertedId });
|
||||
userGetMock.mockResolvedValue({ name: "bob" } as any);
|
||||
userUpdateStreakMock.mockResolvedValue(0);
|
||||
userCheckIfTagPbMock.mockResolvedValue([]);
|
||||
userCheckIfPbMock.mockResolvedValue(true);
|
||||
resultAddMock.mockResolvedValue({ insertedId });
|
||||
});
|
||||
|
||||
it("should add result", async () => {
|
||||
|
|
@ -749,7 +763,7 @@ describe("result controller test", () => {
|
|||
insertedId: insertedId.toHexString(),
|
||||
});
|
||||
|
||||
expect(addResultMock).toHaveBeenCalledWith(
|
||||
expect(resultAddMock).toHaveBeenCalledWith(
|
||||
uid,
|
||||
expect.objectContaining({
|
||||
acc: 86,
|
||||
|
|
@ -783,6 +797,17 @@ describe("result controller test", () => {
|
|||
wpm: 80,
|
||||
})
|
||||
);
|
||||
|
||||
expect(publicUpdateStatsMock).toHaveBeenCalledWith(
|
||||
4,
|
||||
15.1 + 2 - 5 //duration + incompleteTestSeconds-afk
|
||||
);
|
||||
expect(userIncrementXpMock).toHaveBeenCalledWith(uid, 0);
|
||||
expect(userUpdateTypingStatsMock).toHaveBeenCalledWith(
|
||||
uid,
|
||||
4,
|
||||
15.1 + 2 - 5 //duration + incompleteTestSeconds-afk
|
||||
);
|
||||
});
|
||||
it("should fail if result saving is disabled", async () => {
|
||||
//GIVEN
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import * as ApeKeysDal from "../../../src/dal/ape-keys";
|
|||
import * as LogDal from "../../../src/dal/logs";
|
||||
import { ObjectId } from "mongodb";
|
||||
import { PersonalBest } from "@monkeytype/schemas/shared";
|
||||
import { pb } from "../../dal/leaderboards.spec";
|
||||
import {
|
||||
mockAuthenticateWithApeKey,
|
||||
mockBearerAuthentication,
|
||||
|
|
@ -31,6 +30,7 @@ import { MonkeyMail, UserStreak } from "@monkeytype/schemas/users";
|
|||
import MonkeyError, { isFirebaseError } from "../../../src/utils/error";
|
||||
import { LeaderboardEntry } from "@monkeytype/schemas/leaderboards";
|
||||
import * as WeeklyXpLeaderboard from "../../../src/services/weekly-xp-leaderboard";
|
||||
import { pb } from "../../__testData__/users";
|
||||
|
||||
const mockApp = request(app);
|
||||
const configuration = Configuration.getCachedConfiguration();
|
||||
|
|
@ -41,43 +41,7 @@ describe("user controller test", () => {
|
|||
beforeEach(() => {
|
||||
mockAuth.beforeEach();
|
||||
});
|
||||
describe("user creation flow", () => {
|
||||
beforeEach(async () => {
|
||||
await enableSignup(true);
|
||||
});
|
||||
it("should be able to check name, sign up, and get user data", async () => {
|
||||
await mockApp.get("/users/checkName/NewUser").expect(200);
|
||||
|
||||
const newUser = {
|
||||
name: "NewUser",
|
||||
uid,
|
||||
email: "newuser@mail.com",
|
||||
captcha: "captcha",
|
||||
};
|
||||
|
||||
await mockApp
|
||||
.post("/users/signup")
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.send(newUser)
|
||||
.expect(200);
|
||||
|
||||
const response = await mockApp
|
||||
.get("/users")
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const {
|
||||
body: { data: userData },
|
||||
} = response;
|
||||
|
||||
expect(userData.name).toBe(newUser.name);
|
||||
expect(userData.email).toBe(newUser.email);
|
||||
expect(userData.uid).toBe(newUser.uid);
|
||||
|
||||
await mockApp.get("/users/checkName/NewUser").expect(409);
|
||||
});
|
||||
});
|
||||
describe("user signup", () => {
|
||||
const blocklistContainsMock = vi.spyOn(BlocklistDal, "contains");
|
||||
const firebaseDeleteUserMock = vi.spyOn(AuthUtils, "deleteUser");
|
||||
|
|
@ -253,6 +217,64 @@ describe("user controller test", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe("checkName", () => {
|
||||
const userIsNameAvailableMock = vi.spyOn(UserDal, "isNameAvailable");
|
||||
|
||||
beforeEach(() => {
|
||||
userIsNameAvailableMock.mockReset();
|
||||
});
|
||||
|
||||
it("returns ok if name is available", async () => {
|
||||
//GIVEN
|
||||
userIsNameAvailableMock.mockResolvedValue(true);
|
||||
|
||||
//WHEN
|
||||
const { body } = await mockApp
|
||||
.get("/users/checkName/bob")
|
||||
//no authentication required
|
||||
.expect(200);
|
||||
|
||||
//THEN
|
||||
expect(body).toEqual({
|
||||
message: "Username available",
|
||||
data: null,
|
||||
});
|
||||
expect(userIsNameAvailableMock).toHaveBeenCalledWith("bob", "");
|
||||
});
|
||||
|
||||
it("returns 409 if name is not available", async () => {
|
||||
//GIVEN
|
||||
userIsNameAvailableMock.mockResolvedValue(false);
|
||||
|
||||
//WHEN
|
||||
const { body } = await mockApp
|
||||
.get("/users/checkName/bob")
|
||||
//no authentication required
|
||||
.expect(409);
|
||||
|
||||
//THEN
|
||||
expect(body.message).toEqual("Username unavailable");
|
||||
|
||||
expect(userIsNameAvailableMock).toHaveBeenCalledWith("bob", "");
|
||||
});
|
||||
it("returns ok if name is our own", async () => {
|
||||
//GIVEN
|
||||
userIsNameAvailableMock.mockResolvedValue(true);
|
||||
|
||||
//WHEN
|
||||
const { body } = await mockApp
|
||||
.get("/users/checkName/bob")
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.expect(200);
|
||||
|
||||
//THEN
|
||||
expect(body).toEqual({
|
||||
message: "Username available",
|
||||
data: null,
|
||||
});
|
||||
expect(userIsNameAvailableMock).toHaveBeenCalledWith("bob", uid);
|
||||
});
|
||||
});
|
||||
describe("sendVerificationEmail", () => {
|
||||
const adminGetUserMock = vi.fn();
|
||||
const adminGenerateVerificationLinkMock = vi.fn();
|
||||
|
|
@ -602,6 +624,7 @@ describe("user controller test", () => {
|
|||
"purgeUserFromXpLeaderboards"
|
||||
);
|
||||
const blocklistAddMock = vi.spyOn(BlocklistDal, "add");
|
||||
const logsDeleteUserMock = vi.spyOn(LogDal, "deleteUserLogs");
|
||||
|
||||
beforeEach(() => {
|
||||
mockAuth.beforeEach();
|
||||
|
|
@ -631,6 +654,7 @@ describe("user controller test", () => {
|
|||
deleteAllPresetsMock,
|
||||
purgeUserFromDailyLeaderboardsMock,
|
||||
purgeUserFromXpLeaderboardsMock,
|
||||
logsDeleteUserMock,
|
||||
].forEach((it) => it.mockReset());
|
||||
});
|
||||
|
||||
|
|
@ -668,6 +692,7 @@ describe("user controller test", () => {
|
|||
uid,
|
||||
(await configuration).leaderboards.weeklyXp
|
||||
);
|
||||
expect(logsDeleteUserMock).toHaveBeenCalledWith(uid);
|
||||
});
|
||||
it("should delete user without adding to blocklist if not banned", async () => {
|
||||
//GIVEN
|
||||
|
|
@ -702,6 +727,7 @@ describe("user controller test", () => {
|
|||
uid,
|
||||
(await configuration).leaderboards.weeklyXp
|
||||
);
|
||||
expect(logsDeleteUserMock).toHaveBeenCalledWith(uid);
|
||||
});
|
||||
|
||||
it("should not fail if userInfo cannot be found", async () => {
|
||||
|
|
@ -731,6 +757,7 @@ describe("user controller test", () => {
|
|||
uid,
|
||||
(await configuration).leaderboards.weeklyXp
|
||||
);
|
||||
expect(logsDeleteUserMock).toHaveBeenCalledWith(uid);
|
||||
});
|
||||
|
||||
it("should fail for unknown error from UserDal", async () => {
|
||||
|
|
@ -759,6 +786,7 @@ describe("user controller test", () => {
|
|||
uid,
|
||||
(await configuration).leaderboards.weeklyXp
|
||||
);
|
||||
expect(logsDeleteUserMock).not.toHaveBeenCalled();
|
||||
});
|
||||
it("should not fail if firebase user cannot be found", async () => {
|
||||
//GIVEN
|
||||
|
|
@ -798,6 +826,7 @@ describe("user controller test", () => {
|
|||
uid,
|
||||
(await configuration).leaderboards.weeklyXp
|
||||
);
|
||||
expect(logsDeleteUserMock).toHaveBeenCalledWith(uid);
|
||||
});
|
||||
|
||||
it("should fail for unknown error from firebase", async () => {
|
||||
|
|
@ -3392,9 +3421,8 @@ describe("user controller test", () => {
|
|||
//WHEN
|
||||
const { body } = await mockApp
|
||||
.patch("/users/inbox")
|
||||
.set("Authorization", `Bearer ${uid}`);
|
||||
//.expect(200);
|
||||
console.log(body);
|
||||
.set("Authorization", `Bearer ${uid}`)
|
||||
.expect(200);
|
||||
|
||||
//THEN
|
||||
expect(body).toEqual({
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import * as MongoDbMock from "vitest-mongodb";
|
||||
import { isIntegrationTest } from "./__integration__";
|
||||
export async function setup(): Promise<void> {
|
||||
process.env.TZ = "UTC";
|
||||
await MongoDbMock.setup(MongoDbMockConfig);
|
||||
if (isIntegrationTest) {
|
||||
console.log("integration download mongomock");
|
||||
await MongoDbMock.setup(MongoDbMockConfig);
|
||||
}
|
||||
}
|
||||
|
||||
export async function teardown(): Promise<void> {
|
||||
await MongoDbMock.teardown();
|
||||
if (isIntegrationTest) {
|
||||
await MongoDbMock.teardown();
|
||||
}
|
||||
}
|
||||
|
||||
export const MongoDbMockConfig = {
|
||||
|
|
|
|||
40
backend/__tests__/setup-common-mocks.ts
Normal file
40
backend/__tests__/setup-common-mocks.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
export function setupCommonMocks() {
|
||||
vi.mock("../src/utils/logger", () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
error: console.error,
|
||||
warning: console.warn,
|
||||
info: console.info,
|
||||
success: console.info,
|
||||
logToDb: console.info,
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("swagger-stats", () => ({
|
||||
getMiddleware:
|
||||
() =>
|
||||
(_: unknown, __: unknown, next: () => unknown): void => {
|
||||
next();
|
||||
},
|
||||
}));
|
||||
|
||||
// TODO: better approach for this when needed
|
||||
// https://firebase.google.com/docs/rules/unit-tests#run_local_unit_tests_with_the_version_9_javascript_sdk
|
||||
vi.mock("firebase-admin", () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
auth: (): unknown => ({
|
||||
verifyIdToken: (
|
||||
_token: string,
|
||||
_checkRevoked: boolean
|
||||
): unknown /* Promise<DecodedIdToken> */ =>
|
||||
Promise.resolve({
|
||||
aud: "mockFirebaseProjectId",
|
||||
auth_time: 123,
|
||||
exp: 1000,
|
||||
uid: "mockUid",
|
||||
}),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
|
@ -1,94 +1,51 @@
|
|||
import { Collection, Db, MongoClient, WithId } from "mongodb";
|
||||
import { afterAll, beforeAll, afterEach } from "vitest";
|
||||
import * as MongoDbMock from "vitest-mongodb";
|
||||
import { MongoDbMockConfig } from "./global-setup";
|
||||
import { isIntegrationTest } from "./__integration__";
|
||||
import { BASE_CONFIGURATION } from "../src/constants/base-configuration";
|
||||
import { setupCommonMocks } from "./setup-common-mocks";
|
||||
|
||||
process.env["MODE"] = "dev";
|
||||
//process.env["MONGOMS_DISTRO"] = "ubuntu-22.04";
|
||||
|
||||
if (isIntegrationTest) {
|
||||
console.error("wrong environment");
|
||||
process.exit();
|
||||
}
|
||||
|
||||
if (!process.env["REDIS_URI"]) {
|
||||
// use mock if not set
|
||||
process.env["REDIS_URI"] = "redis://mock";
|
||||
}
|
||||
|
||||
let db: Db;
|
||||
let client: MongoClient;
|
||||
const collectionsForCleanUp = ["users"];
|
||||
|
||||
beforeAll(async () => {
|
||||
//don't add any configuration here, add to global-setup.ts instead.
|
||||
await MongoDbMock.setup(MongoDbMockConfig);
|
||||
|
||||
client = new MongoClient(globalThis.__MONGO_URI__);
|
||||
await client.connect();
|
||||
db = client.db();
|
||||
vi.mock("../src/dal/logs", () => ({
|
||||
addLog: vi.fn(),
|
||||
addImportantLog: vi.fn(),
|
||||
deleteUserLogs: vi.fn(),
|
||||
}));
|
||||
vi.mock("../src/init/configuration", () => ({
|
||||
getLiveConfiguration: () => BASE_CONFIGURATION,
|
||||
getCachedConfiguration: () => BASE_CONFIGURATION,
|
||||
patchConfiguration: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../src/init/db", () => ({
|
||||
__esModule: true,
|
||||
getDb: (): Db => db,
|
||||
collection: <T>(name: string): Collection<WithId<T>> =>
|
||||
db.collection<WithId<T>>(name),
|
||||
getDb: () => undefined,
|
||||
collection: () => undefined,
|
||||
close: () => {
|
||||
//
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../src/utils/logger", () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
error: console.error,
|
||||
warning: console.warn,
|
||||
info: console.info,
|
||||
success: console.info,
|
||||
logToDb: console.info,
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("swagger-stats", () => ({
|
||||
getMiddleware:
|
||||
() =>
|
||||
(_: unknown, __: unknown, next: () => unknown): void => {
|
||||
next();
|
||||
},
|
||||
}));
|
||||
|
||||
// TODO: better approach for this when needed
|
||||
// https://firebase.google.com/docs/rules/unit-tests#run_local_unit_tests_with_the_version_9_javascript_sdk
|
||||
vi.mock("firebase-admin", () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
auth: (): unknown => ({
|
||||
verifyIdToken: (
|
||||
_token: string,
|
||||
_checkRevoked: boolean
|
||||
): unknown /* Promise<DecodedIdToken> */ =>
|
||||
Promise.resolve({
|
||||
aud: "mockFirebaseProjectId",
|
||||
auth_time: 123,
|
||||
exp: 1000,
|
||||
uid: "mockUid",
|
||||
}),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
setupCommonMocks();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (globalThis.__MONGO_URI__) {
|
||||
await Promise.all(
|
||||
collectionsForCleanUp.map((collection) =>
|
||||
db.collection(collection).deleteMany({})
|
||||
)
|
||||
);
|
||||
}
|
||||
//noting
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await client?.close();
|
||||
await MongoDbMock.teardown();
|
||||
// @ts-ignore
|
||||
db = undefined;
|
||||
//@ts-ignore
|
||||
client = undefined;
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
"clean": "tsc --build --clean",
|
||||
"ts-check": "tsc --noEmit",
|
||||
"start": "node ./dist/server.js",
|
||||
"test": "vitest run",
|
||||
"test": "vitest run --exclude '__tests__/__integration__'",
|
||||
"integration-test": "INTEGRATION_TESTS=true vitest run __integration__",
|
||||
"test-coverage": "vitest run --coverage",
|
||||
"dev": "concurrently -p none \"tsx watch --clear-screen=false --inspect ./src/server.ts\" \"tsc --preserveWatchOutput --noEmit --watch\" \"esw src/ -w --ext .ts --cache --color\"",
|
||||
"knip": "knip",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import { defineConfig } from "vitest/config";
|
||||
|
||||
const isIntegrationTest = process.env["INTEGRATION_TESTS"] === "true";
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "node",
|
||||
globalSetup: "__tests__/global-setup.ts",
|
||||
setupFiles: ["__tests__/setup-tests.ts"],
|
||||
setupFiles: isIntegrationTest
|
||||
? ["__tests__/__integration__/setup-integration-tests.ts"]
|
||||
: ["__tests__/setup-tests.ts"],
|
||||
pool: "forks", //this should be the default value, however the CI fails without this set.
|
||||
|
||||
coverage: {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
"build-fe": "turbo run build --filter @monkeytype/frontend",
|
||||
"build-pkg": "turbo run build --filter=\"./packages/*\"",
|
||||
"test": "turbo run test",
|
||||
"test-be": "turbo run test --filter @monkeytype/backend",
|
||||
"test-be": "turbo run test --filter @monkeytype/backend && turbo run integration-test --filter @monkeytype/backend",
|
||||
"test-fe": "turbo run test --filter @monkeytype/frontend",
|
||||
"test-pkg": "turbo run test --filter=\"./packages/*\"",
|
||||
"dev": "turbo run dev --force",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
"dependsOn": ["^build"],
|
||||
"cache": false
|
||||
},
|
||||
"integration-test": {
|
||||
"dependsOn": ["^build"],
|
||||
"cache": false
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["^build"],
|
||||
"persistent": true,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue