Files
jiang13-bbs/frontend/lib/siteUrl.test.ts
freefire 4f3f3a265c feat: 友链/书库/移动端导航/排行榜等多模块功能
新增模块:
- 友链(friendlink)后端处理 + 前端管理页与友链板
- 书库(library):导入、章节、封面、阅读页、横竖版自适应 AdaptiveCoverSlot
- 顶栏导航(header_nav)配置与 MobileTabBar/MobileRailDrawers 移动端抽屉
- 排行榜 service 测试、站点页面测试、时间线发布(timeline_release)

其它改动:
- 后端 handlers/services 全量小幅调整
- 前端组件、库函数、URL/品牌/站点 URL 工具更新
- Lightbox 图片、MdEntries 条目卡、coverColor 派生色相等前端能力
2026-09-30 16:30:07 +08:00

140 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { afterEach, describe, it } from "node:test";
import {
absoluteCanonical,
canonicalPage,
canonicalPath,
homeCanonicalQuery,
isTrackingParam,
isWideShellPath,
parseSiteOrigin,
resolveSiteOrigin,
} from "./siteUrl.ts";
const prev = {
SITE_URL: process.env.SITE_URL,
NODE_ENV: process.env.NODE_ENV,
};
afterEach(() => {
if (prev.SITE_URL === undefined) delete process.env.SITE_URL;
else process.env.SITE_URL = prev.SITE_URL;
process.env.NODE_ENV = prev.NODE_ENV;
});
describe("parseSiteOrigin", () => {
it("去掉尾斜杠并保留端口", () => {
assert.equal(parseSiteOrigin("https://bbs.example.com/"), "https://bbs.example.com");
assert.equal(parseSiteOrigin("http://localhost:3000/"), "http://localhost:3000");
});
it("拒绝 API / 容器名 / 带路径 / 非 http", () => {
assert.equal(parseSiteOrigin("http://api:3001"), null);
assert.equal(parseSiteOrigin("https://bbs.example.com/forum"), null);
assert.equal(parseSiteOrigin("ftp://bbs.example.com"), null);
assert.equal(parseSiteOrigin("not-a-url"), null);
assert.equal(parseSiteOrigin(""), null);
});
it("生产态把容器 API 地址视为非法", () => {
process.env.SITE_URL = "http://api:3001";
process.env.NODE_ENV = "production";
assert.equal(resolveSiteOrigin(), null);
});
});
describe("resolveSiteOrigin", () => {
it("开发态无配置回退 localhost:3000", () => {
delete process.env.SITE_URL;
process.env.NODE_ENV = "development";
assert.equal(resolveSiteOrigin(), "http://localhost:3000");
});
it("生产态缺失不回退 localhost", () => {
delete process.env.SITE_URL;
process.env.NODE_ENV = "production";
assert.equal(resolveSiteOrigin(), null);
});
it("生产态使用 SITE_URL", () => {
process.env.SITE_URL = "https://bbs.example.com/";
process.env.NODE_ENV = "production";
assert.equal(resolveSiteOrigin(), "https://bbs.example.com");
});
});
describe("canonicalPath", () => {
it("首页无尾斜杠参数", () => {
assert.equal(canonicalPath("/"), "/");
assert.equal(canonicalPath("/post/12/"), "/post/12");
});
it("省略空值并丢掉追踪参数", () => {
assert.equal(
canonicalPath("/post/12", { utm_source: "x", fbclid: "1", page: 2, q: "" }),
"/post/12?page=2"
);
});
it("保留内容参数", () => {
assert.equal(canonicalPath("/", { board: 3, sort: "new", page: 2 }), "/?board=3&page=2&sort=new");
});
});
describe("canonicalPage", () => {
it("第一页与非法页码省略", () => {
assert.equal(canonicalPage(undefined), undefined);
assert.equal(canonicalPage("1"), undefined);
assert.equal(canonicalPage("0"), undefined);
assert.equal(canonicalPage("foo"), undefined);
assert.equal(canonicalPage("2"), 2);
});
});
describe("isTrackingParam", () => {
it("识别 utm 与常见点击 id", () => {
assert.equal(isTrackingParam("utm_source"), true);
assert.equal(isTrackingParam("gclid"), true);
assert.equal(isTrackingParam("page"), false);
});
});
describe("absoluteCanonical", () => {
it("拼出绝对地址", () => {
process.env.SITE_URL = "https://bbs.example.com";
process.env.NODE_ENV = "production";
assert.equal(absoluteCanonical("/post/9", { page: 2 }), "https://bbs.example.com/post/9?page=2");
});
});
describe("homeCanonicalQuery", () => {
it("默认排序与第一页省略;搜索丢掉 board", () => {
assert.deepEqual(homeCanonicalQuery({}, true), {});
assert.deepEqual(homeCanonicalQuery({ sort: "latest", page: "1" }, true), {});
assert.deepEqual(homeCanonicalQuery({ sort: "new" }, false), {});
assert.deepEqual(
homeCanonicalQuery({ q: " go ", board: "3", page: "2" }, true),
{ q: "go", page: 2 }
);
assert.deepEqual(
homeCanonicalQuery({ board: "3", sort: "new", page: "2" }, true),
{ board: 3, page: 2, sort: "new" }
);
});
});
describe("isWideShellPath(书库页放宽档位)", () => {
it("覆盖三种伪静态风格的书库路径", () => {
assert.equal(isWideShellPath("/library"), true);
assert.equal(isWideShellPath("/library/abc"), true);
assert.equal(isWideShellPath("/library/abc/read"), true);
assert.equal(isWideShellPath("/library.html"), true);
assert.equal(isWideShellPath("/library-abc.html"), true);
assert.equal(isWideShellPath("/library-abc.html?sec=2"), true);
assert.equal(isWideShellPath("/library-abc-read-2.html"), true);
});
it("非书库路径不放宽", () => {
assert.equal(isWideShellPath("/"), false);
assert.equal(isWideShellPath("/post-1.html"), false);
assert.equal(isWideShellPath("/p-about.html"), false);
assert.equal(isWideShellPath("/u/5"), false);
assert.equal(isWideShellPath("/admin/library"), false);
assert.equal(isWideShellPath("/my-library.html"), false);
assert.equal(isWideShellPath(null), false);
});
});