Public: anyone can read this; the crew can change it.
A milestone's limb links encode `under`, and a test pins `milestoneHref` and `limbHref` #6669
Check · Review · Land · Live done — Landed and live in production.
scout/forge:scout/6659-a-milestone-s-limb-links-encode-under-an → main 1 commit fork
2 files
changed +22
−1
src/web/pages/milestones.ts +1 −1
| @@ -68,7 +68,7 @@ export const limbHref = ( | ||
| 68 | 68 | action: LimbAction | "replan", |
| 69 | 69 | under?: string, |
| 70 | 70 | ): string => |
| 71 | `${milestoneHref(base, number)}/limb?action=${action}${under === undefined ? "" : `&under=${under}`}`; | |
| 71 | `${milestoneHref(base, number)}/limb?action=${action}${under === undefined ? "" : `&under=${encodeURIComponent(under)}`}`; | |
| 72 | 72 | |
| 73 | 73 | /** |
| 74 | 74 | * Raise and Lower for a limb among its siblings in one group (`top`, or a |
test/milestones-href.test.ts added +21
| @@ -0,0 +1,21 @@ | ||
| 1 | import { expect, test } from "bun:test"; | |
| 2 | import { limbHref, milestoneHref } from "../src/web/pages/milestones.ts"; | |
| 3 | ||
| 4 | test("milestoneHref is the base, /milestones/, and the number", () => { | |
| 5 | expect(milestoneHref("/a/b", 7)).toBe("/a/b/milestones/7"); | |
| 6 | }); | |
| 7 | ||
| 8 | test("limbHref names the action, and `under` only when given", () => { | |
| 9 | expect(limbHref("/a/b", 7, "defer")).toBe("/a/b/milestones/7/limb?action=defer"); | |
| 10 | expect(limbHref("/a/b", 7, "raise", "top")).toBe( | |
| 11 | "/a/b/milestones/7/limb?action=raise&under=top", | |
| 12 | ); | |
| 13 | }); | |
| 14 | ||
| 15 | test("limbHref encodes `under` so & and # cannot cut the link", () => { | |
| 16 | const href = limbHref("/a/b", 7, "lower", "x&y#z"); | |
| 17 | expect(href).toBe("/a/b/milestones/7/limb?action=lower&under=x%26y%23z"); | |
| 18 | const q = new URL(href, "http://x").searchParams; | |
| 19 | expect(q.get("under")).toBe("x&y#z"); | |
| 20 | expect(q.get("action")).toBe("lower"); | |
| 21 | }); |
new above
offline