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

community.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.

community.test.tsBlame242 lines · 1 contributor
f9e7c01Claude1/**
2 * Block J12 — Community health scorecard tests.
3 *
4 * Pure helpers + route smoke.
5 */
6
7import { describe, it, expect } from "bun:test";
8import app from "../app";
9import {
10 CHECKLIST,
11 buildReport,
12 checklistFromInputs,
13 isCodeOfConduct,
14 isContributing,
15 isLicense,
16 isPrTemplate,
17 isReadme,
18} from "../lib/community";
19
20describe("community — name matchers", () => {
21 it("isReadme matches all common spellings", () => {
22 expect(isReadme("README")).toBe(true);
23 expect(isReadme("readme.md")).toBe(true);
24 expect(isReadme("Readme.MD")).toBe(true);
25 expect(isReadme("README.txt")).toBe(true);
26 expect(isReadme("README.rst")).toBe(true);
27 expect(isReadme("readme.markdown")).toBe(true);
28 });
29
30 it("isReadme rejects look-alikes", () => {
31 expect(isReadme("readme.html")).toBe(false);
32 expect(isReadme("not-readme.md")).toBe(false);
33 expect(isReadme("READMEFIRST.md")).toBe(false);
34 });
35
36 it("isLicense matches LICENSE / LICENCE / COPYING variants", () => {
37 expect(isLicense("LICENSE")).toBe(true);
38 expect(isLicense("License.md")).toBe(true);
39 expect(isLicense("LICENCE.txt")).toBe(true);
40 expect(isLicense("COPYING")).toBe(true);
41 });
42
43 it("isLicense rejects unrelated files", () => {
44 expect(isLicense("licensing.md")).toBe(false);
45 expect(isLicense("license-check.md")).toBe(false);
46 });
47
48 it("isCodeOfConduct matches common separators", () => {
49 expect(isCodeOfConduct("CODE_OF_CONDUCT.md")).toBe(true);
50 expect(isCodeOfConduct("code-of-conduct.md")).toBe(true);
51 expect(isCodeOfConduct("CodeOfConduct")).toBe(true);
52 });
53
54 it("isContributing matches case-insensitively", () => {
55 expect(isContributing("CONTRIBUTING.md")).toBe(true);
56 expect(isContributing("contributing")).toBe(true);
57 expect(isContributing("contributing.txt")).toBe(true);
58 expect(isContributing("contributors.md")).toBe(false);
59 });
60
61 it("isPrTemplate matches expected spellings", () => {
62 expect(isPrTemplate("pull_request_template.md")).toBe(true);
63 expect(isPrTemplate("PULL_REQUEST_TEMPLATE")).toBe(true);
64 expect(isPrTemplate("pull-request-template.md")).toBe(true);
65 expect(isPrTemplate("PR_TEMPLATE.md")).toBe(false);
66 });
67});
68
69describe("community — CHECKLIST table", () => {
70 it("exposes eight items with unique keys", () => {
71 expect(CHECKLIST.length).toBe(8);
72 const keys = new Set(CHECKLIST.map((c) => c.key));
73 expect(keys.size).toBe(8);
74 });
75
76 it("marks description/readme/license required; others recommended", () => {
77 const required = new Set(
78 CHECKLIST.filter((i) => i.required).map((i) => i.key)
79 );
80 expect(required.has("description")).toBe(true);
81 expect(required.has("readme")).toBe(true);
82 expect(required.has("license")).toBe(true);
83 expect(required.has("code_of_conduct")).toBe(false);
84 expect(required.has("pr_template")).toBe(false);
85 });
86});
87
88describe("community — checklistFromInputs", () => {
89 const empty = {
90 rootEntries: [],
91 githubEntries: [],
92 issueTemplateDirExists: false,
93 description: null,
94 topics: [],
95 };
96
97 it("all-zero input → all checks false", () => {
98 const r = checklistFromInputs(empty);
99 for (const key of Object.keys(r) as Array<keyof typeof r>) {
100 expect(r[key]).toBe(false);
101 }
102 });
103
104 it("detects README at root + README in .github", () => {
105 expect(
106 checklistFromInputs({ ...empty, rootEntries: ["README.md"] }).readme
107 ).toBe(true);
108 expect(
109 checklistFromInputs({ ...empty, githubEntries: ["README.md"] }).readme
110 ).toBe(true);
111 });
112
113 it("LICENSE variants all count", () => {
114 for (const n of ["LICENSE", "License.md", "LICENCE.txt", "COPYING"]) {
115 expect(
116 checklistFromInputs({ ...empty, rootEntries: [n] }).license
117 ).toBe(true);
118 }
119 });
120
121 it("description requires non-empty trimmed text", () => {
122 expect(checklistFromInputs({ ...empty, description: "" }).description).toBe(false);
123 expect(
124 checklistFromInputs({ ...empty, description: " " }).description
125 ).toBe(false);
126 expect(checklistFromInputs({ ...empty, description: "x" }).description).toBe(true);
127 });
128
129 it("topics requires at least one", () => {
130 expect(checklistFromInputs({ ...empty, topics: [] }).topics).toBe(false);
131 expect(checklistFromInputs({ ...empty, topics: ["ai"] }).topics).toBe(true);
132 });
133
134 it("issue_template is present if dir exists OR a single file", () => {
135 expect(
136 checklistFromInputs({ ...empty, issueTemplateDirExists: true })
137 .issue_template
138 ).toBe(true);
139 expect(
140 checklistFromInputs({
141 ...empty,
142 rootEntries: ["ISSUE_TEMPLATE.md"],
143 }).issue_template
144 ).toBe(true);
145 expect(
146 checklistFromInputs({
147 ...empty,
148 githubEntries: ["ISSUE_TEMPLATE.md"],
149 }).issue_template
150 ).toBe(true);
151 });
152
153 it("pr_template — accepts .github/ and root spellings", () => {
154 expect(
155 checklistFromInputs({
156 ...empty,
157 githubEntries: ["pull_request_template.md"],
158 }).pr_template
159 ).toBe(true);
160 expect(
161 checklistFromInputs({
162 ...empty,
163 rootEntries: ["PULL_REQUEST_TEMPLATE.md"],
164 }).pr_template
165 ).toBe(true);
166 });
167});
168
169describe("community — buildReport", () => {
170 it("all-false → 0% / meetsRequired false", () => {
171 const r = buildReport({
172 description: false,
173 readme: false,
174 license: false,
175 code_of_conduct: false,
176 contributing: false,
177 issue_template: false,
178 pr_template: false,
179 topics: false,
180 });
181 expect(r.score).toBe(0);
182 expect(r.passed).toBe(0);
183 expect(r.total).toBe(8);
184 expect(r.requiredPassed).toBe(0);
185 expect(r.requiredTotal).toBe(3);
186 expect(r.meetsRequired).toBe(false);
187 });
188
189 it("all-true → 100% / meetsRequired true", () => {
190 const r = buildReport({
191 description: true,
192 readme: true,
193 license: true,
194 code_of_conduct: true,
195 contributing: true,
196 issue_template: true,
197 pr_template: true,
198 topics: true,
199 });
200 expect(r.score).toBe(100);
201 expect(r.meetsRequired).toBe(true);
202 });
203
204 it("required-only → meetsRequired true, score partial", () => {
205 const r = buildReport({
206 description: true,
207 readme: true,
208 license: true,
209 code_of_conduct: false,
210 contributing: false,
211 issue_template: false,
212 pr_template: false,
213 topics: false,
214 });
215 expect(r.meetsRequired).toBe(true);
216 expect(r.score).toBe(Math.round((3 / 8) * 100));
217 });
218
219 it("preserves CHECKLIST ordering + annotates `present`", () => {
220 const r = buildReport({
221 description: true,
222 readme: false,
223 license: false,
224 code_of_conduct: false,
225 contributing: false,
226 issue_template: false,
227 pr_template: false,
228 topics: false,
229 });
230 expect(r.items[0].key).toBe("description");
231 expect(r.items[0].present).toBe(true);
232 expect(r.items[1].key).toBe("readme");
233 expect(r.items[1].present).toBe(false);
234 });
235});
236
237describe("community — route", () => {
238 it("GET /:o/:r/community on missing repo returns 404", async () => {
239 const res = await app.request("/alice/nope/community");
240 expect(res.status).toBe(404);
241 });
242});