test: add recover/email-change branch coverage tests (TDD)
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 21m29s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 21m29s
This commit is contained in:
parent
20e6c8ce8c
commit
e0c4214e53
2 changed files with 122 additions and 0 deletions
44
src/__tests__/email-change-branch-coverage.test.ts
Normal file
44
src/__tests__/email-change-branch-coverage.test.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import express from "express";
|
||||
import request from "supertest";
|
||||
|
||||
vi.mock("../services/db.js");
|
||||
vi.mock("../services/logger.js", () => ({
|
||||
default: { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() },
|
||||
}));
|
||||
|
||||
let app: express.Express;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
|
||||
const { queryWithRetry } = await import("../services/db.js");
|
||||
vi.mocked(queryWithRetry).mockResolvedValue({ rows: [], rowCount: 0 } as any);
|
||||
|
||||
const { emailChangeRouter } = await import("../routes/email-change.js");
|
||||
app = express();
|
||||
app.use(express.json());
|
||||
app.use("/email-change", emailChangeRouter);
|
||||
});
|
||||
|
||||
describe("email-change branch coverage", () => {
|
||||
// Line 16: req.body being falsy in rate limiter keyGenerator — covered implicitly
|
||||
// Line 75: req.body being falsy in POST / handler
|
||||
it("POST /email-change with no body returns 400", async () => {
|
||||
const res = await request(app)
|
||||
.post("/email-change")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("null");
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
// Line 171: req.body being falsy in POST /verify handler
|
||||
it("POST /email-change/verify with no body returns 400", async () => {
|
||||
const res = await request(app)
|
||||
.post("/email-change/verify")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("null");
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
});
|
||||
78
src/__tests__/recover-branch-coverage.test.ts
Normal file
78
src/__tests__/recover-branch-coverage.test.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import express from "express";
|
||||
import request from "supertest";
|
||||
|
||||
vi.mock("../services/db.js");
|
||||
vi.mock("../services/logger.js", () => ({
|
||||
default: { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() },
|
||||
}));
|
||||
|
||||
let app: express.Express;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetModules();
|
||||
|
||||
const { createPendingVerification, verifyCode } = await import("../services/verification.js");
|
||||
const { sendVerificationEmail } = await import("../services/email.js");
|
||||
const { getAllKeys } = await import("../services/keys.js");
|
||||
const { queryWithRetry } = await import("../services/db.js");
|
||||
|
||||
vi.mocked(createPendingVerification).mockResolvedValue({ email: "test@test.com", code: "654321", createdAt: "", expiresAt: "", attempts: 0 });
|
||||
vi.mocked(verifyCode).mockResolvedValue({ status: "ok" });
|
||||
vi.mocked(sendVerificationEmail).mockResolvedValue(true);
|
||||
vi.mocked(getAllKeys).mockReturnValue([]);
|
||||
vi.mocked(queryWithRetry).mockResolvedValue({ rows: [], rowCount: 0 } as any);
|
||||
|
||||
const { recoverRouter } = await import("../routes/recover.js");
|
||||
app = express();
|
||||
app.use(express.json());
|
||||
app.use("/recover", recoverRouter);
|
||||
});
|
||||
|
||||
describe("recover branch coverage", () => {
|
||||
// Line 61: req.body being falsy (no body sent) — hits `req.body || {}` fallback
|
||||
it("POST /recover with no body returns 400", async () => {
|
||||
const res = await request(app)
|
||||
.post("/recover")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("null");
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
// Line 151: req.body being falsy in verify endpoint
|
||||
it("POST /recover/verify with no body returns 400", async () => {
|
||||
const res = await request(app)
|
||||
.post("/recover/verify")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("null");
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
// Line 181: row.created_at instanceof Date — when DB returns a Date object
|
||||
it("POST /recover/verify handles Date object for created_at in DB fallback", async () => {
|
||||
const { verifyCode } = await import("../services/verification.js");
|
||||
const { getAllKeys } = await import("../services/keys.js");
|
||||
const { queryWithRetry } = await import("../services/db.js");
|
||||
|
||||
vi.mocked(verifyCode).mockResolvedValue({ status: "ok" });
|
||||
vi.mocked(getAllKeys).mockReturnValue([]); // Force DB fallback
|
||||
vi.mocked(queryWithRetry).mockResolvedValue({
|
||||
rows: [{
|
||||
key: "recovered-key",
|
||||
tier: "pro",
|
||||
email: "found@test.com",
|
||||
created_at: new Date("2026-01-15T10:00:00Z"), // Date object, not string
|
||||
stripe_customer_id: null,
|
||||
}],
|
||||
rowCount: 1,
|
||||
} as any);
|
||||
|
||||
const res = await request(app)
|
||||
.post("/recover/verify")
|
||||
.send({ email: "found@test.com", code: "654321" });
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body.apiKey).toBe("recovered-key");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue