test: improve coverage for health.ts and email-change.ts
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 20m41s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 20m41s
- Add test for health.ts: client.query() error path with client.release(true) - Add test for email-change.ts: sendVerificationEmail failure (fire-and-forget) - Add test for email-change.ts verify: invalid API key (403 response) Coverage improvements: - health.ts: 87.09% → 100% lines (covered lines 84-85) - email-change.ts: 94.33% → 100% lines, 80% → 100% functions (covered lines 112, 176-177) - Overall: 92.73% → 93.13% lines (+0.40%) - Total tests: 722 → 725 (+3)
This commit is contained in:
parent
99b67f2584
commit
8f70a32f77
2 changed files with 58 additions and 0 deletions
|
|
@ -90,6 +90,27 @@ describe("POST /v1/email-change", () => {
|
|||
expect(res.status).toBe(200);
|
||||
expect(res.body.status).toBe("verification_sent");
|
||||
});
|
||||
|
||||
it("does not crash when sendVerificationEmail fails (fire-and-forget)", async () => {
|
||||
const { sendVerificationEmail } = await import("../services/email.js");
|
||||
const logger = (await import("../services/logger.js")).default;
|
||||
|
||||
vi.mocked(sendVerificationEmail).mockRejectedValue(new Error("SMTP connection failed"));
|
||||
|
||||
const res = await request(app).post("/v1/email-change").send({ apiKey: "df_pro_xxx", newEmail: "new@example.com" });
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body.status).toBe("verification_sent");
|
||||
|
||||
// Give the catch handler a moment to execute
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
|
||||
// Verify error was logged
|
||||
expect(logger.error).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ email: "new@example.com" }),
|
||||
"Failed to send email change verification"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /v1/email-change/verify", () => {
|
||||
|
|
@ -98,6 +119,24 @@ describe("POST /v1/email-change/verify", () => {
|
|||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
it("returns 403 for invalid API key", async () => {
|
||||
const { queryWithRetry } = await import("../services/db.js");
|
||||
vi.mocked(queryWithRetry).mockImplementation((async (sql: string) => {
|
||||
if (sql.includes("SELECT") && sql.includes("key =")) {
|
||||
return { rows: [], rowCount: 0 };
|
||||
}
|
||||
return { rows: [], rowCount: 0 };
|
||||
}) as any);
|
||||
|
||||
const res = await request(app).post("/v1/email-change/verify").send({
|
||||
apiKey: "fake",
|
||||
newEmail: "new@example.com",
|
||||
code: "123456"
|
||||
});
|
||||
expect(res.status).toBe(403);
|
||||
expect(res.body.error).toContain("Invalid API key");
|
||||
});
|
||||
|
||||
it("returns 400 for invalid code", async () => {
|
||||
const { verifyCode } = await import("../services/verification.js");
|
||||
vi.mocked(verifyCode).mockResolvedValue({ status: "invalid" });
|
||||
|
|
|
|||
|
|
@ -65,4 +65,23 @@ describe("GET /health", () => {
|
|||
expect(res.body.version).toBeDefined();
|
||||
expect(typeof res.body.version).toBe("string");
|
||||
});
|
||||
|
||||
it("returns 503 when client.query() throws and releases client with destroy flag", async () => {
|
||||
const mockRelease = vi.fn();
|
||||
const mockClient = {
|
||||
query: vi.fn().mockRejectedValue(new Error("Query failed")),
|
||||
release: mockRelease,
|
||||
};
|
||||
vi.mocked(pool.connect).mockResolvedValue(mockClient as any);
|
||||
|
||||
const res = await request(app).get("/health");
|
||||
|
||||
expect(res.status).toBe(503);
|
||||
expect(res.body.status).toBe("degraded");
|
||||
expect(res.body.database.status).toBe("error");
|
||||
expect(res.body.database.message).toContain("Query failed");
|
||||
|
||||
// Verify client.release(true) was called to destroy the bad connection
|
||||
expect(mockRelease).toHaveBeenCalledWith(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue