aboutsummaryrefslogtreecommitdiffhomepage
path: root/pkgs/server/src/routes/auth.test.ts
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-12-06 17:05:21 +0900
committernsfisis <nsfisis@gmail.com>2025-12-06 17:37:04 +0900
commit811458427593a4172a2cd535cc768db375350dca (patch)
tree6c4f46c96b6f29392dc19d591e39e03c187033a1 /pkgs/server/src/routes/auth.test.ts
parent9736a8981fbd6c6defbd67517ca23904fc844629 (diff)
downloadkioku-811458427593a4172a2cd535cc768db375350dca.tar.gz
kioku-811458427593a4172a2cd535cc768db375350dca.tar.zst
kioku-811458427593a4172a2cd535cc768db375350dca.zip
feat(dev): change architecture and directory structure
Diffstat (limited to 'pkgs/server/src/routes/auth.test.ts')
-rw-r--r--pkgs/server/src/routes/auth.test.ts428
1 files changed, 0 insertions, 428 deletions
diff --git a/pkgs/server/src/routes/auth.test.ts b/pkgs/server/src/routes/auth.test.ts
deleted file mode 100644
index 34eb2b6..0000000
--- a/pkgs/server/src/routes/auth.test.ts
+++ /dev/null
@@ -1,428 +0,0 @@
-import { Hono } from "hono";
-import { beforeEach, describe, expect, it, vi } from "vitest";
-import { errorHandler } from "../middleware";
-import type {
- RefreshTokenRepository,
- UserPublic,
- UserRepository,
-} from "../repositories";
-import { createAuthRouter } from "./auth";
-
-vi.mock("argon2", () => ({
- hash: vi.fn((password: string) => Promise.resolve(`hashed_${password}`)),
- verify: vi.fn((hash: string, password: string) =>
- Promise.resolve(hash === `hashed_${password}`),
- ),
-}));
-
-function createMockUserRepo(): UserRepository {
- return {
- findByUsername: vi.fn(),
- existsByUsername: vi.fn(),
- create: vi.fn(),
- findById: vi.fn(),
- };
-}
-
-function createMockRefreshTokenRepo(): RefreshTokenRepository {
- return {
- findValidToken: vi.fn(),
- create: vi.fn(),
- deleteById: vi.fn(),
- };
-}
-
-interface RegisterResponse {
- user?: {
- id: string;
- username: string;
- createdAt: string;
- };
- error?: {
- code: string;
- message: string;
- };
-}
-
-interface LoginResponse {
- accessToken?: string;
- refreshToken?: string;
- user?: {
- id: string;
- username: string;
- };
- error?: {
- code: string;
- message: string;
- };
-}
-
-describe("POST /register", () => {
- let app: Hono;
- let mockUserRepo: ReturnType<typeof createMockUserRepo>;
- let mockRefreshTokenRepo: ReturnType<typeof createMockRefreshTokenRepo>;
-
- beforeEach(() => {
- vi.clearAllMocks();
- mockUserRepo = createMockUserRepo();
- mockRefreshTokenRepo = createMockRefreshTokenRepo();
- const auth = createAuthRouter({
- userRepo: mockUserRepo,
- refreshTokenRepo: mockRefreshTokenRepo,
- });
- app = new Hono();
- app.onError(errorHandler);
- app.route("/api/auth", auth);
- });
-
- it("creates a new user with valid credentials", async () => {
- vi.mocked(mockUserRepo.existsByUsername).mockResolvedValue(false);
- vi.mocked(mockUserRepo.create).mockResolvedValue({
- id: "test-uuid-123",
- username: "testuser",
- createdAt: new Date("2024-01-01T00:00:00Z"),
- } as UserPublic);
-
- const res = await app.request("/api/auth/register", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "testuser",
- password: "securepassword12345",
- }),
- });
-
- expect(res.status).toBe(201);
- const body = (await res.json()) as RegisterResponse;
- expect(body.user).toEqual({
- id: "test-uuid-123",
- username: "testuser",
- createdAt: "2024-01-01T00:00:00.000Z",
- });
- expect(mockUserRepo.existsByUsername).toHaveBeenCalledWith("testuser");
- expect(mockUserRepo.create).toHaveBeenCalledWith({
- username: "testuser",
- passwordHash: "hashed_securepassword12345",
- });
- });
-
- it("returns 422 for invalid username", async () => {
- const res = await app.request("/api/auth/register", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "",
- password: "securepassword12345",
- }),
- });
-
- expect(res.status).toBe(422);
- const body = (await res.json()) as RegisterResponse;
- expect(body.error?.code).toBe("VALIDATION_ERROR");
- });
-
- it("returns 422 for password too short", async () => {
- const res = await app.request("/api/auth/register", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "testuser",
- password: "tooshort123456",
- }),
- });
-
- expect(res.status).toBe(422);
- const body = (await res.json()) as RegisterResponse;
- expect(body.error?.code).toBe("VALIDATION_ERROR");
- });
-
- it("returns 409 for existing username", async () => {
- vi.mocked(mockUserRepo.existsByUsername).mockResolvedValue(true);
-
- const res = await app.request("/api/auth/register", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "existinguser",
- password: "securepassword12345",
- }),
- });
-
- expect(res.status).toBe(409);
- const body = (await res.json()) as RegisterResponse;
- expect(body.error?.code).toBe("USERNAME_EXISTS");
- });
-});
-
-describe("POST /login", () => {
- let app: Hono;
- let mockUserRepo: ReturnType<typeof createMockUserRepo>;
- let mockRefreshTokenRepo: ReturnType<typeof createMockRefreshTokenRepo>;
-
- beforeEach(() => {
- vi.clearAllMocks();
- mockUserRepo = createMockUserRepo();
- mockRefreshTokenRepo = createMockRefreshTokenRepo();
- const auth = createAuthRouter({
- userRepo: mockUserRepo,
- refreshTokenRepo: mockRefreshTokenRepo,
- });
- app = new Hono();
- app.onError(errorHandler);
- app.route("/api/auth", auth);
- });
-
- it("returns access token for valid credentials", async () => {
- vi.mocked(mockUserRepo.findByUsername).mockResolvedValue({
- id: "user-uuid-123",
- username: "testuser",
- passwordHash: "hashed_correctpassword",
- });
- vi.mocked(mockRefreshTokenRepo.create).mockResolvedValue(undefined);
-
- const res = await app.request("/api/auth/login", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "testuser",
- password: "correctpassword",
- }),
- });
-
- expect(res.status).toBe(200);
- const body = (await res.json()) as LoginResponse;
- expect(body.accessToken).toBeDefined();
- expect(typeof body.accessToken).toBe("string");
- expect(body.refreshToken).toBeDefined();
- expect(typeof body.refreshToken).toBe("string");
- expect(body.user).toEqual({
- id: "user-uuid-123",
- username: "testuser",
- });
- expect(mockRefreshTokenRepo.create).toHaveBeenCalledWith({
- userId: "user-uuid-123",
- tokenHash: expect.any(String),
- expiresAt: expect.any(Date),
- });
- });
-
- it("returns 401 for non-existent user", async () => {
- vi.mocked(mockUserRepo.findByUsername).mockResolvedValue(undefined);
-
- const res = await app.request("/api/auth/login", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "nonexistent",
- password: "anypassword",
- }),
- });
-
- expect(res.status).toBe(401);
- const body = (await res.json()) as LoginResponse;
- expect(body.error?.code).toBe("INVALID_CREDENTIALS");
- });
-
- it("returns 401 for incorrect password", async () => {
- vi.mocked(mockUserRepo.findByUsername).mockResolvedValue({
- id: "user-uuid-123",
- username: "testuser",
- passwordHash: "hashed_correctpassword",
- });
-
- const res = await app.request("/api/auth/login", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "testuser",
- password: "wrongpassword",
- }),
- });
-
- expect(res.status).toBe(401);
- const body = (await res.json()) as LoginResponse;
- expect(body.error?.code).toBe("INVALID_CREDENTIALS");
- });
-
- it("returns 422 for missing username", async () => {
- const res = await app.request("/api/auth/login", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "",
- password: "somepassword",
- }),
- });
-
- expect(res.status).toBe(422);
- const body = (await res.json()) as LoginResponse;
- expect(body.error?.code).toBe("VALIDATION_ERROR");
- });
-
- it("returns 422 for missing password", async () => {
- const res = await app.request("/api/auth/login", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- username: "testuser",
- password: "",
- }),
- });
-
- expect(res.status).toBe(422);
- const body = (await res.json()) as LoginResponse;
- expect(body.error?.code).toBe("VALIDATION_ERROR");
- });
-});
-
-interface RefreshResponse {
- accessToken?: string;
- refreshToken?: string;
- user?: {
- id: string;
- username: string;
- };
- error?: {
- code: string;
- message: string;
- };
-}
-
-describe("POST /refresh", () => {
- let app: Hono;
- let mockUserRepo: ReturnType<typeof createMockUserRepo>;
- let mockRefreshTokenRepo: ReturnType<typeof createMockRefreshTokenRepo>;
-
- beforeEach(() => {
- vi.clearAllMocks();
- mockUserRepo = createMockUserRepo();
- mockRefreshTokenRepo = createMockRefreshTokenRepo();
- const auth = createAuthRouter({
- userRepo: mockUserRepo,
- refreshTokenRepo: mockRefreshTokenRepo,
- });
- app = new Hono();
- app.onError(errorHandler);
- app.route("/api/auth", auth);
- });
-
- it("returns new tokens for valid refresh token", async () => {
- vi.mocked(mockRefreshTokenRepo.findValidToken).mockResolvedValue({
- id: "token-id-123",
- userId: "user-uuid-123",
- expiresAt: new Date(Date.now() + 86400000),
- });
- vi.mocked(mockUserRepo.findById).mockResolvedValue({
- id: "user-uuid-123",
- username: "testuser",
- });
- vi.mocked(mockRefreshTokenRepo.deleteById).mockResolvedValue(undefined);
- vi.mocked(mockRefreshTokenRepo.create).mockResolvedValue(undefined);
-
- const res = await app.request("/api/auth/refresh", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- refreshToken: "valid-refresh-token-hex",
- }),
- });
-
- expect(res.status).toBe(200);
- const body = (await res.json()) as RefreshResponse;
- expect(body.accessToken).toBeDefined();
- expect(typeof body.accessToken).toBe("string");
- expect(body.refreshToken).toBeDefined();
- expect(typeof body.refreshToken).toBe("string");
- expect(body.user).toEqual({
- id: "user-uuid-123",
- username: "testuser",
- });
- expect(mockRefreshTokenRepo.deleteById).toHaveBeenCalledWith(
- "token-id-123",
- );
- expect(mockRefreshTokenRepo.create).toHaveBeenCalledWith({
- userId: "user-uuid-123",
- tokenHash: expect.any(String),
- expiresAt: expect.any(Date),
- });
- });
-
- it("returns 401 for invalid refresh token", async () => {
- vi.mocked(mockRefreshTokenRepo.findValidToken).mockResolvedValue(undefined);
-
- const res = await app.request("/api/auth/refresh", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- refreshToken: "invalid-refresh-token",
- }),
- });
-
- expect(res.status).toBe(401);
- const body = (await res.json()) as RefreshResponse;
- expect(body.error?.code).toBe("INVALID_REFRESH_TOKEN");
- });
-
- it("returns 401 for expired refresh token", async () => {
- vi.mocked(mockRefreshTokenRepo.findValidToken).mockResolvedValue(undefined);
-
- const res = await app.request("/api/auth/refresh", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- refreshToken: "expired-refresh-token",
- }),
- });
-
- expect(res.status).toBe(401);
- const body = (await res.json()) as RefreshResponse;
- expect(body.error?.code).toBe("INVALID_REFRESH_TOKEN");
- });
-
- it("returns 401 when user not found", async () => {
- vi.mocked(mockRefreshTokenRepo.findValidToken).mockResolvedValue({
- id: "token-id-123",
- userId: "deleted-user-id",
- expiresAt: new Date(Date.now() + 86400000),
- });
- vi.mocked(mockUserRepo.findById).mockResolvedValue(undefined);
-
- const res = await app.request("/api/auth/refresh", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- refreshToken: "valid-refresh-token",
- }),
- });
-
- expect(res.status).toBe(401);
- const body = (await res.json()) as RefreshResponse;
- expect(body.error?.code).toBe("USER_NOT_FOUND");
- });
-
- it("returns 422 for missing refresh token", async () => {
- const res = await app.request("/api/auth/refresh", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({}),
- });
-
- expect(res.status).toBe(422);
- const body = (await res.json()) as RefreshResponse;
- expect(body.error?.code).toBe("VALIDATION_ERROR");
- });
-
- it("returns 422 for empty refresh token", async () => {
- const res = await app.request("/api/auth/refresh", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- refreshToken: "",
- }),
- });
-
- expect(res.status).toBe(422);
- const body = (await res.json()) as RefreshResponse;
- expect(body.error?.code).toBe("VALIDATION_ERROR");
- });
-});