mmday-firebase/tests/services/userService.test.ts
윤정민 f98fa84da8 feat: user endpoint update
기존 유저 관련 엔드포인트를 /user로 전부 통합해서 관리할 수 있도록 수정 및 테스트 코드 추가
2026-04-13 13:21:04 +09:00

103 lines
3.2 KiB
TypeScript

import { beforeEach, describe, expect, it } from "vitest";
import type { DecodedIdToken } from "firebase-admin/auth";
import { firestore } from "../../src/firebase.js";
import { createMe, getMe } from "../../src/services/userService.js";
import { HttpError } from "../../src/middleware/errors.js";
const uid = "user-1";
function fakeToken(overrides: Partial<DecodedIdToken> = {}): DecodedIdToken {
return {
uid,
email: "tester@example.com",
picture: "https://cdn.example.com/p.png",
firebase: {
identities: {},
sign_in_provider: "google.com",
},
aud: "test",
auth_time: 0,
exp: 0,
iat: 0,
iss: "test",
sub: uid,
...overrides,
} as DecodedIdToken;
}
const validBody = {
displayName: "유저1",
favoriteTeamCode: "LG",
knowledgeLevel: "casual",
};
describe("userService", () => {
beforeEach(async () => {
await firestore.recursiveDelete(firestore.collection("users"));
});
describe("getMe", () => {
it("미존재 유저는 404 + USER_NOT_FOUND", async () => {
await expect(getMe(uid)).rejects.toMatchObject({
status: 404,
code: "USER_NOT_FOUND",
});
});
it("존재하는 유저를 반환한다", async () => {
await createMe(fakeToken(), validBody);
const u = await getMe(uid);
expect(u.displayName).toBe("유저1");
expect(u.favoriteTeamCode).toBe("LG");
expect(u.knowledgeLevel).toBe("casual");
});
});
describe("createMe", () => {
it("정상 생성 시 토큰의 email/photo/provider를 사용한다", async () => {
const u = await createMe(fakeToken(), validBody);
expect(u.email).toBe("tester@example.com");
expect(u.photoUrl).toBe("https://cdn.example.com/p.png");
expect(u.provider).toBe("google");
expect(u.favoriteTeamCode).toBe("LG");
expect(u.knowledgeLevel).toBe("casual");
});
it("apple.com 프로바이더 매핑", async () => {
const t = fakeToken({
firebase: { identities: {}, sign_in_provider: "apple.com" },
});
const u = await createMe(t, validBody);
expect(u.provider).toBe("apple");
});
it("중복 생성 시 409 + USER_ALREADY_EXISTS", async () => {
await createMe(fakeToken(), validBody);
await expect(createMe(fakeToken(), validBody)).rejects.toMatchObject({
status: 409,
code: "USER_ALREADY_EXISTS",
});
});
it.each([
["빈 displayName", { ...validBody, displayName: "" }],
["11자 displayName", { ...validBody, displayName: "1234567890X" }],
["숫자 displayName", { ...validBody, displayName: 123 }],
["잘못된 팀코드", { ...validBody, favoriteTeamCode: "XX" }],
["잘못된 레벨", { ...validBody, knowledgeLevel: "master" }],
])("%s → 400 INVALID_INPUT", async (_label, body) => {
await expect(createMe(fakeToken(), body as never)).rejects.toMatchObject({
status: 400,
code: "INVALID_INPUT",
});
});
it("지원하지 않는 provider → 400", async () => {
const t = fakeToken({
firebase: { identities: {}, sign_in_provider: "password" },
});
await expect(createMe(t, validBody)).rejects.toBeInstanceOf(HttpError);
});
});
});