|
| 1 | +/** |
| 2 | + * Regression tests for content-path resolution via transformUri. |
| 3 | + * |
| 4 | + * The bug these guard against: uppercaseWords used a plain `.includes()` + |
| 5 | + * `.replace()`, so the token "Zec" matched as a *prefix* of "Zecmap" / |
| 6 | + * "ZecHub" and rewrote the content path to a non-existent file |
| 7 | + * (`ZECmap.md` instead of `Zecmap.md`). The page then rendered the empty |
| 8 | + * "Browse the articles…" placeholder at HTTP 200. |
| 9 | + * |
| 10 | + * Fix: only rewrite whole path segments (bounded by start/end, `/`, or `_`). |
| 11 | + * |
| 12 | + * helpers.ts imports getRootCached from authAndFetch (for firstFileForFolders), |
| 13 | + * which pulls in next/cache. Mock that module so this pure unit test never |
| 14 | + * loads the Next server runtime (TextEncoder / unstable_cache). |
| 15 | + */ |
| 16 | + |
| 17 | +jest.mock("../authAndFetch", () => ({ |
| 18 | + getRootCached: jest.fn(async () => []), |
| 19 | +})); |
| 20 | + |
| 21 | +import { transformUri, getDynamicRoute, resolveContentPath } from "../helpers"; |
| 22 | + |
| 23 | +describe("transformUri — whole-segment uppercase/lowercase words", () => { |
| 24 | + it("does not rewrite Zec inside Zecmap", () => { |
| 25 | + expect(transformUri("/using-zcash/zecmap")).toBe("/Using_Zcash/Zecmap"); |
| 26 | + }); |
| 27 | + |
| 28 | + it("still uppercases a standalone Zec segment to ZEC", () => { |
| 29 | + expect(transformUri("/using-zcash/buying-zec")).toBe( |
| 30 | + "/Using_Zcash/Buying_ZEC", |
| 31 | + ); |
| 32 | + }); |
| 33 | + |
| 34 | + it("uppercases Frost → FROST as a whole segment", () => { |
| 35 | + expect(transformUri("/zcash-tech/frost")).toBe("/Zcash_Tech/FROST"); |
| 36 | + }); |
| 37 | + |
| 38 | + it("uppercases Nft → NFT as a whole segment", () => { |
| 39 | + expect(transformUri("/zcash-community/cypherpunk-zero-nft")).toBe( |
| 40 | + "/Zcash_Community/Cypherpunk_Zero_NFT", |
| 41 | + ); |
| 42 | + }); |
| 43 | + |
| 44 | + it("maps Zechub → ZecHub via specialWordsMap (no greedy Zec prefix rewrite)", () => { |
| 45 | + // Capitalize → What_Is_Zechub; lowercase Is → What_is_Zechub; |
| 46 | + // whole-segment rules leave Zechub intact; specialWordsMap → ZecHub. |
| 47 | + expect(transformUri("/start-here/what-is-zechub")).toBe( |
| 48 | + "/Start_Here/What_is_ZecHub", |
| 49 | + ); |
| 50 | + }); |
| 51 | + |
| 52 | + it("handles ZEC_Use_Cases (standalone Zec segment)", () => { |
| 53 | + expect(transformUri("/start-here/zec-use-cases")).toBe( |
| 54 | + "/Start_Here/ZEC_Use_Cases", |
| 55 | + ); |
| 56 | + }); |
| 57 | + |
| 58 | + it("handles zk_SNARKS (Zk lowered + Snarks uppercased)", () => { |
| 59 | + expect(transformUri("/zcash-tech/zk-snarks")).toBe( |
| 60 | + "/Zcash_Tech/zk_SNARKS", |
| 61 | + ); |
| 62 | + }); |
| 63 | + |
| 64 | + it("maps contribute/zechub-dao to ZecHub_DAO", () => { |
| 65 | + expect(transformUri("/contribute/zechub-dao")).toBe( |
| 66 | + "/contribute/ZecHub_DAO", |
| 67 | + ); |
| 68 | + }); |
| 69 | + |
| 70 | + it("maps contribute/zecweekly-newsletter to ZecWeekly_Newsletter", () => { |
| 71 | + expect(transformUri("/contribute/zecweekly-newsletter")).toBe( |
| 72 | + "/contribute/ZecWeekly_Newsletter", |
| 73 | + ); |
| 74 | + }); |
| 75 | +}); |
| 76 | + |
| 77 | +describe("getDynamicRoute / resolveContentPath", () => { |
| 78 | + it("resolves zecmap to the real content filename", () => { |
| 79 | + expect(getDynamicRoute(["using-zcash", "zecmap"])).toBe( |
| 80 | + "/site/Using_Zcash/Zecmap.md", |
| 81 | + ); |
| 82 | + expect(resolveContentPath(["using-zcash", "zecmap"])).toBe( |
| 83 | + "/site/Using_Zcash/Zecmap.md", |
| 84 | + ); |
| 85 | + }); |
| 86 | + |
| 87 | + it("resolves buying-zec to Buying_ZEC.md", () => { |
| 88 | + expect(getDynamicRoute(["using-zcash", "buying-zec"])).toBe( |
| 89 | + "/site/Using_Zcash/Buying_ZEC.md", |
| 90 | + ); |
| 91 | + }); |
| 92 | +}); |
0 commit comments