From 98863df648462ac22bc6b43a1d565c207481cc98 Mon Sep 17 00:00:00 2001 From: cuixiaorui Date: Sat, 20 Jul 2024 10:27:31 +0800 Subject: [PATCH] test(api): add test for user service --- apps/api/src/user/tests/user.service.spec.ts | 179 +++++++++++++++++++ apps/api/src/user/user.service.ts | 5 +- 2 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 apps/api/src/user/tests/user.service.spec.ts diff --git a/apps/api/src/user/tests/user.service.spec.ts b/apps/api/src/user/tests/user.service.spec.ts new file mode 100644 index 00000000..372015c1 --- /dev/null +++ b/apps/api/src/user/tests/user.service.spec.ts @@ -0,0 +1,179 @@ +import { Test, TestingModule } from "@nestjs/testing"; + +import { insertCourse, insertCoursePack } from "../../../test/fixture/db"; +import { cleanDB, testImportModules } from "../../../test/helper/utils"; +import { endDB } from "../../common/db"; +import { DB, DbType } from "../../global/providers/db.provider"; +import { LogtoService } from "../../logto/logto.service"; +import { MembershipService } from "../../membership/membership.service"; +import { UserCourseProgressService } from "../../user-course-progress/user-course-progress.service"; +import { UserService } from "../user.service"; + +describe("UserService", () => { + let db: DbType; + let userService: UserService; + let logtoServiceMock: jest.Mocked; + let membershipServiceMock: jest.Mocked; + let userCourseProgressServiceMock: jest.Mocked; + + beforeAll(async () => { + const testHelper = await setupTesting(); + db = testHelper.db; + userService = testHelper.userService; + logtoServiceMock = testHelper.logtoService as jest.Mocked; + membershipServiceMock = testHelper.membershipService as jest.Mocked; + userCourseProgressServiceMock = + testHelper.userCourseProgressService as jest.Mocked; + }); + + afterAll(async () => { + await cleanDB(db); + await endDB(); + }); + + beforeEach(async () => { + await cleanDB(db); + jest.clearAllMocks(); + }); + + describe("findUser", () => { + it("should return user info with membership details when user is a member", async () => { + const userId = "testUserId"; + const logtoUserInfo = { id: userId, name: "Test User" }; + const membershipDetails = { + type: "founder", + startDate: new Date(), + endDate: new Date(), + isActive: true, + }; + (logtoServiceMock.logtoApi.get as jest.Mock).mockResolvedValue({ data: logtoUserInfo }); + membershipServiceMock.isMember.mockResolvedValue(true); + membershipServiceMock.getMembershipDetails.mockResolvedValue(membershipDetails); + + const result = await userService.findUser(userId); + + expect(result).toEqual({ + ...logtoUserInfo, + membership: { + isMember: true, + details: membershipDetails, + }, + }); + }); + + it("should return user info without membership details when user is not a member", async () => { + const userId = "testUserId"; + const logtoUserInfo = { id: userId, name: "Test User" }; + + (logtoServiceMock.logtoApi.get as jest.Mock).mockResolvedValue({ data: logtoUserInfo }); + membershipServiceMock.isMember.mockResolvedValue(false); + + const result = await userService.findUser(userId); + + expect(result).toEqual({ + ...logtoUserInfo, + membership: { + isMember: false, + details: null, + }, + }); + }); + + it("should return undefined when there's an error fetching user info", async () => { + const userId = "testUserId"; + + (logtoServiceMock.logtoApi.get as jest.Mock).mockRejectedValue(new Error("API Error")); + + const result = await userService.findUser(userId); + + expect(result).toBeUndefined(); + }); + }); + + describe("setupNewUser", () => { + it("should setup a new user with provided username and avatar", async () => { + const user = { userId: "newUserId" }; + const dto = { username: "newUser", avatar: "custom-avatar.png" }; + jest.spyOn(userService as any, "updateUser").mockResolvedValue({}); + + const coursePackEntity = await insertCoursePack(db); + const courseEntity = await insertCourse(db, coursePackEntity.id); + + const result = await userService.setupNewUser(user, dto); + + expect(result).toEqual({ + avatar: dto.avatar, + username: dto.username, + }); + expect(userService.updateUser).toHaveBeenCalledWith(user, dto); + expect(userCourseProgressServiceMock.upsert).toHaveBeenCalledWith( + user.userId, + coursePackEntity.id, + courseEntity.id, + 0, + ); + }); + + it("should use default avatar if not provided", async () => { + const user = { userId: "newUserId" }; + const dto = { username: "newUser", avatar: "" }; + jest.spyOn(userService as any, "updateUser").mockResolvedValue({}); + jest.spyOn(userService as any, "getRandomNumber").mockReturnValue(5); // 模拟随机数 + const coursePackEntity = await insertCoursePack(db); + const courseEntity = await insertCourse(db, coursePackEntity.id); + const result = await userService.setupNewUser(user, dto); + + const expectedAvatar = + "https://earthworm-prod-1312884695.cos.ap-beijing.myqcloud.com/avatars/avatar5.png"; + expect(result).toEqual({ + avatar: expectedAvatar, + username: dto.username, + }); + expect(userService.updateUser).toHaveBeenCalledWith(user, { + username: dto.username, + avatar: expectedAvatar, + }); + expect(userCourseProgressServiceMock.upsert).toHaveBeenCalledWith( + user.userId, + coursePackEntity.id, + courseEntity.id, + 0, + ); + }); + }); +}); + +async function setupTesting() { + const logtoServiceMock = { + logtoApi: { + get: jest.fn(), + patch: jest.fn(), + }, + }; + + const membershipServiceMock = { + isMember: jest.fn(), + getMembershipDetails: jest.fn(), + }; + const userCourseProgressServiceMock = { + upsert: jest.fn(), + }; + + const moduleRef: TestingModule = await Test.createTestingModule({ + imports: testImportModules, + providers: [ + UserService, + { provide: LogtoService, useValue: logtoServiceMock }, + { provide: MembershipService, useValue: membershipServiceMock }, + { provide: UserCourseProgressService, useValue: userCourseProgressServiceMock }, + ], + }).compile(); + + return { + db: moduleRef.get(DB), + userService: moduleRef.get(UserService), + logtoService: moduleRef.get(LogtoService), + membershipService: moduleRef.get(MembershipService), + userCourseProgressService: moduleRef.get(UserCourseProgressService), + }; +} diff --git a/apps/api/src/user/user.service.ts b/apps/api/src/user/user.service.ts index cdaa0407..04df2f6f 100644 --- a/apps/api/src/user/user.service.ts +++ b/apps/api/src/user/user.service.ts @@ -55,9 +55,8 @@ export class UserService { } async setupNewUser(user: UserEntity, dto: { username: string; avatar: string }) { - const avatar = this.getAvatarUrl(); if (!dto.avatar) { - dto.avatar = avatar; + dto.avatar = this.getAvatarUrl(); } await this.updateUser(user, { username: dto.username, avatar: dto.avatar }); @@ -73,7 +72,7 @@ export class UserService { await this.userCourseProgressService.upsert(user.userId, id, courses.at(0).id, 0); return { - avatar, + avatar: dto.avatar, username: dto.username, }; }