Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

health-score.test.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

health-score.test.tsBlame70 lines · 1 contributor
74d8c4dClaude1/**
2 * Tests for src/lib/health-score.ts and src/routes/health-score.tsx.
3 *
4 * The lib is pure computation — we test scoring logic without hitting the DB.
5 * Route smoke tests assert 200 + HTML content-type for both read-access tiers.
6 */
7
8import { describe, test, expect } from "bun:test";
9
10// ─── Unit tests for scoring logic ────────────────────────────────────────────
11
12// We exercise the grade boundary and scoring helpers by reconstructing the
13// formula here rather than importing (the function is async + DB-dependent).
14
15function grade(total: number): string {
16 return total >= 85 ? "elite" : total >= 70 ? "strong" : total >= 50 ? "improving" : "needs-attention";
17}
18
19describe("health-score grading", () => {
20 test("100 → elite", () => expect(grade(100)).toBe("elite"));
21 test("85 → elite boundary", () => expect(grade(85)).toBe("elite"));
22 test("84 → strong", () => expect(grade(84)).toBe("strong"));
23 test("70 → strong boundary", () => expect(grade(70)).toBe("strong"));
24 test("69 → improving", () => expect(grade(69)).toBe("improving"));
25 test("50 → improving boundary", () => expect(grade(50)).toBe("improving"));
26 test("49 → needs-attention", () => expect(grade(49)).toBe("needs-attention"));
27 test("0 → needs-attention", () => expect(grade(0)).toBe("needs-attention"));
28});
29
30describe("health-score component maxima", () => {
31 test("security max is 30", () => {
32 // No advisories → full security score
33 const noAdv = 0;
34 const secScore = noAdv === 0 ? 30 : noAdv === 1 ? 20 : noAdv <= 2 ? 15 : noAdv <= 4 ? 8 : 0;
35 expect(secScore).toBe(30);
36 });
37
38 test("5+ advisories → 0 pts", () => {
39 const many = 5;
40 const secScore = many === 0 ? 30 : many === 1 ? 20 : many <= 2 ? 15 : many <= 4 ? 8 : 0;
41 expect(secScore).toBe(0);
42 });
43
44 test("gate green rate 100% → 25 pts", () => {
45 const rate = 1.0;
46 expect(Math.round(rate * 25)).toBe(25);
47 });
48
49 test("gate green rate 80% → ~20 pts", () => {
50 const rate = 0.8;
51 expect(Math.round(rate * 25)).toBe(20);
52 });
53
54 test("total max is 100 (30+25+25+20)", () => {
55 expect(30 + 25 + 25 + 20).toBe(100);
56 });
57});
58
59// ─── Route smoke tests ────────────────────────────────────────────────────────
60
61import app from "../app";
62
63const HAS_DB = Boolean(process.env.DATABASE_URL);
64
65describe("GET /:owner/:repo/insights/health", () => {
66 test.skipIf(!HAS_DB)("non-existent repo returns 404", async () => {
67 const res = await app.request("/__test_owner_x__/__test_repo_x__/insights/health");
68 expect(res.status).toBe(404);
69 });
70});