Skip to content
89 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 type OverviewFacts,
6 POLICY_PATHS,
7 overviewRows,
8 rowsIn,
9 securityPolicyBranch,
10 securityPolicyPullBody,
11 securityPolicyTemplate,
12} from "./security-overview.ts";
13
14const facts = (over: Partial<OverviewFacts> = {}): OverviewFacts => ({
15 base: "/acme/rocket",
16 policyPath: null,
17 reporting: false,
18 advisories: 0,
19 upkeep: true,
20 codeScanning: { configured: false, analyses: 0, entitled: true },
21 historyAlerts: true,
22 canManage: true,
23 canPush: true,
24 ...over,
25});
26
27test("every feature is one row with a status word and one thing to do", () => {
28 const rows = overviewRows(facts());
29 assert.deepEqual(
30 rows.map((row) => [row.key, row.status]),
31 [
32 ["policy", "needs_setup"],
33 ["advisories", "enabled"],
34 ["reporting", "disabled"],
35 ["dependency_alerts", "enabled"],
36 ["security_updates", "enabled"],
37 ["code_scanning", "needs_setup"],
38 ["secret_scanning", "enabled"],
39 ["code_quality", "coming"],
40 ],
41 );
42 // No policy: a pull request adds one, for someone who can push.
43 assert.deepEqual(rows[0].action, { kind: "post", label: "Set up a security policy", action: "/acme/rocket/security/policy/setup", pending: "Opening a pull request…" });
44 // Code scanning not set up: the starter workflow, for an admin on an entitled repository.
45 assert.equal(rows[5].action?.kind, "post");
46 // Switches are for admins; the words say what they switch.
47 assert.deepEqual(rows[2].action, { kind: "switch", label: "Private vulnerability reporting", intent: "reporting", on: false });
48 assert.deepEqual(rows[4].action, { kind: "switch", label: "Security updates", intent: "upkeep", on: true });
49 // Code quality is honest about not being there.
50 assert.equal(rows[7].action, null);
51 assert.equal(rowsIn(rows, "findings").length, 5);
52 assert.equal(rowsIn(rows, "reporting").length, 2);
53});
54
55test("what is on reads as enabled, with a link to it", () => {
56 const rows = overviewRows(facts({ policyPath: "SECURITY.md", reporting: true, advisories: 2, codeScanning: { configured: true, analyses: 3, entitled: true } }));
57 assert.equal(rows[0].status, "enabled");
58 assert.deepEqual(rows[0].action, { kind: "link", label: "View policy", to: "/acme/rocket/blob/HEAD/SECURITY.md" });
59 assert.equal(rows[1].about, "2 published advisories tell people who depend on this repository what to do.");
60 assert.equal(rows[2].status, "enabled");
61 assert.equal(rows[5].status, "enabled");
62 assert.deepEqual(rows[5].action, { kind: "link", label: "View alerts", to: "/acme/rocket/security/code-scanning" });
63});
64
65test("someone who cannot change settings sees the rows without the switches", () => {
66 const rows = overviewRows(facts({ canManage: false, canPush: false, codeScanning: { configured: false, analyses: 0, entitled: false } }));
67 assert.equal(rows[0].action, null);
68 assert.equal(rows[2].action, null);
69 assert.equal(rows[4].action, null);
70 // Code scanning on a private repository without the plan: a page that says so, not a form.
71 assert.deepEqual(rows[5].action, { kind: "link", label: "Learn more", to: "/acme/rocket/security/code-scanning" });
72 assert.match(rows[5].hint ?? "", /g1t plan/);
73 assert.equal(rows[6].hint, "Push protection is always on.");
74 assert.match(overviewRows(facts({ historyAlerts: false }))[6].about, /history are off/);
75});
76
77test("the policy template says how to report and names the private form when it is on", () => {
78 const withForm = securityPolicyTemplate("acme/rocket", true, "/acme/rocket");
79 assert.match(withForm, /^# Security policy/);
80 assert.match(withForm, /https:\/\/g1t\.sh\/acme\/rocket\/security\/report/);
81 assert.match(withForm, /## Supported versions/);
82 const without = securityPolicyTemplate("acme/rocket", false, "/acme/rocket");
83 assert.doesNotMatch(without, /security\/report/);
84 assert.match(without, /Email the maintainers/);
85 assert.match(securityPolicyPullBody("SECURITY.md"), /`SECURITY\.md`/);
86 assert.equal(securityPolicyBranch([]), "add-security-policy");
87 assert.equal(securityPolicyBranch(["add-security-policy", "add-security-policy-2"]), "add-security-policy-3");
88 assert.equal(POLICY_PATHS[0], "SECURITY.md");
89});