Skip to content

Removed ts-ignore statements from codebase and fixed the tests in faulty files #3253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 1, 2025
Merged
Show file tree
Hide file tree
Changes from 6 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
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
import type { FastifyInstance } from "fastify";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, it } from "vitest";
import { type Mock, vi } from "vitest";
import type { z } from "zod";
import type { chatMembershipRoleEnum } from "~/src/drizzle/enums/chatMembershipRole";
import type { organizationMembershipRoleEnum } from "~/src/drizzle/enums/organizationMembershipRole";
import type { userRoleEnum } from "~/src/drizzle/enums/userRole";
import { TalawaGraphQLError } from "~/src/utilities/TalawaGraphQLError";
import type { PubSub } from "../../pubsub";
import { resolveUpdatedAt } from "./updatedAt";
import type { PubSub } from "../../../../src/graphql/pubsub";
import { resolveUpdatedAt } from "../../../../src/graphql/types/Chat/updatedAt";

// Infer types from the zod enums
type UserRole = z.infer<typeof userRoleEnum>;
type ChatMembershipRole = z.infer<typeof chatMembershipRoleEnum>;
type OrganizationMembershipRole = z.infer<
typeof organizationMembershipRoleEnum
>;

type MockUser = {
role: UserRole;
chatMembershipsWhereMember: Array<{ role: ChatMembershipRole }>;
organizationMembershipsWhereMember: Array<{
role: OrganizationMembershipRole;
}>;
};

type MockDrizzleClient = {
query: {
usersTable: {
findFirst: Mock<() => Promise<MockUser | undefined>>;
};
};
};

const mockParent = {
id: "chat_1",
organizationId: "org_1",
Expand All @@ -15,13 +44,14 @@ const mockParent = {
avatarName: "avatar_name",
updaterId: "updater_1",
};

const drizzleClientMock = {
query: {
usersTable: {
findFirst: vi.fn(),
findFirst: vi.fn().mockImplementation(() => Promise.resolve(undefined)),
},
},
} as unknown as FastifyInstance["drizzleClient"];
} as unknown as FastifyInstance["drizzleClient"] & MockDrizzleClient;

const authenticatedContext = {
currentClient: {
Expand Down Expand Up @@ -62,7 +92,6 @@ describe("Chat.updatedAt resolver", () => {
});

it("throws unauthenticated error when user is not found", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue(undefined);

await expect(
Expand All @@ -71,7 +100,6 @@ describe("Chat.updatedAt resolver", () => {
});

it("throws unauthorized error when user lacks permissions", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
role: "regular",
chatMembershipsWhereMember: [],
Expand All @@ -84,7 +112,6 @@ describe("Chat.updatedAt resolver", () => {
});

it("returns updatedAt when user is global admin", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
role: "administrator",
chatMembershipsWhereMember: [],
Expand All @@ -96,7 +123,6 @@ describe("Chat.updatedAt resolver", () => {
});

it("returns updatedAt when user is an administrator in the organization and not global administrator", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
role: "regular",
chatMembershipsWhereMember: [{ role: "regular" }],
Expand All @@ -106,8 +132,8 @@ describe("Chat.updatedAt resolver", () => {
const result = await resolveUpdatedAt(mockParent, {}, authenticatedContext);
expect(result).toEqual(mockParent.updatedAt);
});

it("returns updatedAt when user is a chat administrator and not global administrator", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
role: "regular",
chatMembershipsWhereMember: [{ role: "administrator" }],
Expand All @@ -117,8 +143,8 @@ describe("Chat.updatedAt resolver", () => {
const result = await resolveUpdatedAt(mockParent, {}, authenticatedContext);
expect(result).toEqual(mockParent.updatedAt);
});

it("returns updatedAt when user is both organization and chat admin", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
role: "regular",
chatMembershipsWhereMember: [{ role: "administrator" }],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import type { FastifyInstance } from "fastify";
import { describe, expect, it, vi } from "vitest";
import type { PubSub } from "../../pubsub";
import { resolveEventUpdater } from "./updater";
import { describe, expect, it } from "vitest";
import { type Mock, vi } from "vitest";
import type { z } from "zod";
import type { userRoleEnum } from "~/src/drizzle/enums/userRole";
import type { PubSub } from "../../../../src/graphql/pubsub";
import { resolveEventUpdater } from "../../../../src/graphql/types/Event/updater";

// Define types for the user object structure
type UserRole = z.infer<typeof userRoleEnum>;
type UserObject = {
id: string;
role: UserRole;
organizationMembershipsWhereMember: Array<{ role: UserRole }>;
};

// Define the type for the mock DrizzleClient based on usage
type MockDrizzleClient = {
query: {
usersTable: {
findFirst: Mock<() => Promise<UserObject | undefined>>;
};
};
};

const MockEvent = {
createdAt: new Date(),
creatorId: "user_1",
Expand All @@ -15,13 +36,14 @@ const MockEvent = {
updaterId: "updater_1",
};

// Create a properly typed mock for drizzleClient
const drizzleClientMock = {
query: {
usersTable: {
findFirst: vi.fn(),
},
},
} as unknown as FastifyInstance["drizzleClient"];
} as unknown as FastifyInstance["drizzleClient"] & MockDrizzleClient;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider using mockImplementation for better type safety.

Based on our experience with complex types in Vitest, consider using mockImplementation instead of the direct mock function:

-			findFirst: vi.fn(),
+			findFirst: vi.fn().mockImplementation(() => Promise.resolve(undefined)),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Create a properly typed mock for drizzleClient
const drizzleClientMock = {
query: {
usersTable: {
findFirst: vi.fn(),
},
},
} as unknown as FastifyInstance["drizzleClient"];
} as unknown as FastifyInstance["drizzleClient"] & MockDrizzleClient;
// Create a properly typed mock for drizzleClient
const drizzleClientMock = {
query: {
usersTable: {
findFirst: vi.fn().mockImplementation(() => Promise.resolve(undefined)),
},
},
} as unknown as FastifyInstance["drizzleClient"] & MockDrizzleClient;


const authenticatedContext = {
currentClient: {
Expand All @@ -33,7 +55,7 @@ const authenticatedContext = {
drizzleClient: drizzleClientMock,
envConfig: { API_BASE_URL: "API_BASE" },
log: { error: vi.fn() } as unknown as FastifyInstance["log"],
minio: {} as unknown as FastifyInstance["minio"],
minio: {} as FastifyInstance["minio"],
jwt: {
sign: vi.fn(),
},
Expand Down Expand Up @@ -62,9 +84,9 @@ describe("resolveEventUpdater", async () => {
}),
);
});

it("throws an unauthenticated error if the current user is not found", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockReturnValue(undefined);
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue(undefined);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider consistent mock implementation approach.

For consistency and better type safety, consider using mockImplementation instead of mockResolvedValue across all test cases:

-		drizzleClientMock.query.usersTable.findFirst.mockResolvedValue(undefined);
+		drizzleClientMock.query.usersTable.findFirst.mockImplementation(() => Promise.resolve(undefined));

Also applies to: 101-105, 122-126, 154-156, 173-173, 190-190, 213-215


await expect(
resolveEventUpdater(MockEvent, {}, authenticatedContext),
Expand All @@ -74,12 +96,14 @@ describe("resolveEventUpdater", async () => {
}),
);
});

it("throws unauthorized_action error if current user is not administrator", async () => {
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockReturnValue({
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
id: "user_1",
role: "regular",
organizationMembershipsWhereMember: [{}],
organizationMembershipsWhereMember: [{ role: "regular" }],
});

await expect(
resolveEventUpdater(MockEvent, {}, authenticatedContext),
).rejects.toThrowError(
Expand All @@ -93,17 +117,18 @@ describe("resolveEventUpdater", async () => {
}),
);
});

it("should return user as null if event (parent) has no updaterId ", async () => {
//@ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockReturnValue({
drizzleClientMock.query.usersTable.findFirst.mockResolvedValue({
id: "user_1",
role: "administrator",
organizationMembershipsWhereMember: [{ role: "administrator" }],
});

const eventWithoutUpdater = {
...MockEvent,
updaterId: null,
}; // event with no updater id
};

const result = await resolveEventUpdater(
eventWithoutUpdater,
Expand All @@ -112,15 +137,40 @@ describe("resolveEventUpdater", async () => {
);
expect(result).toBeNull();
});

it("returns the current user if updaterId matches current user's id", async () => {
const mockCurrentUser: UserObject = {
id: "user_1",
role: "administrator",
organizationMembershipsWhereMember: [{ role: "administrator" }],
};

// Mock the event with updaterId matching the current user's id
const eventWithCurrentUserAsUpdater = {
...MockEvent,
updaterId: "user_1", // Same as mockCurrentUser.id
};

drizzleClientMock.query.usersTable.findFirst.mockResolvedValue(
mockCurrentUser,
);

const result = await resolveEventUpdater(
eventWithCurrentUserAsUpdater,
{},
authenticatedContext,
);
expect(result).toEqual(mockCurrentUser);
});

it("returns the currentUser if user is global administrator and event has updaterId", async () => {
// not mocking all the values of the user
const MockUser = {
id: "updater_1", // user with the id same as MockEvent.updaterId
const MockUser: UserObject = {
id: "updater_1",
role: "administrator",
organizationMembershipsWhereMember: [{ role: "regular" }],
};
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockReturnValue(MockUser);

drizzleClientMock.query.usersTable.findFirst.mockResolvedValue(MockUser);

const result = await resolveEventUpdater(
MockEvent,
Expand All @@ -129,35 +179,38 @@ describe("resolveEventUpdater", async () => {
);
expect(result).toEqual(MockUser);
});

it("return currentUser if user is not the global administrator but organization administrator and event has updaterId", async () => {
// not mocking all the values of the user
const MockUser = {
id: "updater_1", // id matches with Event.updaterId
const MockUser: UserObject = {
id: "updater_1",
role: "regular",
organizationMembershipsWhereMember: [{ role: "administrator" }],
};
// @ts-ignore
drizzleClientMock.query.usersTable.findFirst.mockReturnValue(MockUser);
expect(
resolveEventUpdater(MockEvent, {}, authenticatedContext),
).resolves.toEqual(MockUser);

drizzleClientMock.query.usersTable.findFirst.mockResolvedValue(MockUser);

const result = await resolveEventUpdater(
MockEvent,
{},
authenticatedContext,
);
expect(result).toEqual(MockUser);
});

it("returns the updater user if updaterId differs from current user's id", async () => {
const mockCurrentUser = {
const mockCurrentUser: UserObject = {
id: "user_1",
role: "administrator",
organizationMembershipsWhereMember: [{ role: "administrator" }],
};
// user which updated the event
const mockUpdaterUser = {

const mockUpdaterUser: UserObject = {
id: "updater_1",
role: "administrator",
organizationMembershipsWhereMember: [],
organizationMembershipsWhereMember: [{ role: "regular" }],
};
// The first call returns the current user, and the second returns the updater user

drizzleClientMock.query.usersTable.findFirst
// @ts-ignore
.mockResolvedValueOnce(mockCurrentUser)
.mockResolvedValueOnce(mockUpdaterUser);

Expand All @@ -170,14 +223,13 @@ describe("resolveEventUpdater", async () => {
});

it("throws unexpected error when the updaterId user does not exist", async () => {
const mockCurrentUser = {
const mockCurrentUser: UserObject = {
id: "user_1",
role: "administrator",
organizationMembershipsWhereMember: [{ role: "administrator " }],
organizationMembershipsWhereMember: [{ role: "administrator" }],
};

drizzleClientMock.query.usersTable.findFirst
// @ts-ignore
.mockResolvedValueOnce(mockCurrentUser)
.mockResolvedValueOnce(undefined);

Expand Down
Loading