import test from "node:test";
import assert from "node:assert/strict";
import type { ReactNode } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { SiteProvider } from "../src/components/providers/SiteProvider";
import { SiteHeader } from "../src/components/layout/SiteHeader";
import { MobileTabbar } from "../src/components/layout/MobileTabbar";
import { HomePage } from "../src/features/catalog/HomePage";
import { HomeRoadPage } from "../src/features/content/HomeRoadPage";
import { SiteNavigationPage } from "../src/features/content/SiteNavigationPage";
import { brandAssets } from "../src/lib/brand-assets";
import { toPublicPath } from "../src/lib/routes";
import { allListURL, chapterPlayURL, categoryURL, listThemeSegment, listUpdateStatus, moreListURL, moreSeriesListURL, navHasMegaMenu, navHref, navIsActive, navIsDownload, pageURL, videoPlayURL } from "../src/lib/view-helpers";
const data = {
requestPath: "/dramas/", isLoggedIn: true, isRegistered: true, userID: 7,
userName: "观众", recharge: 100, appConfig: {}, config: {},
categoryList: [
{ name: "首页", urlValue: "/", categoryType: 1 },
{ name: "短剧", urlValue: "/list", categoryType: 1 },
{ name: "专题", urlValue: "/topic", categoryType: 1 },
{ name: "排行榜", urlValue: "/rank", categoryType: 1 },
{ name: "回家的路", urlValue: "/home-road/", categoryType: 1 },
],
themeList: [{ id: 1, slug: "romance", name: "爱情" }],
};
const render = (children: ReactNode) => renderToStaticMarkup({children});
const hrefs = (html: string) => [...html.matchAll(/]*\bhref="([^"]*)"/g)].map((match) => match[1].replaceAll("&", "&"));
function assertPublicLinks(html: string): string[] {
const links = hrefs(html);
for (const href of links.filter((value) => value.startsWith("/") && !value.startsWith("//")))
assert.equal(href, toPublicPath(href), "internal link should reach its page directly: " + href);
return links;
}
test("shared view helpers produce business URLs and keep nested menu activation boundaries", () => {
assert.equal(chapterPlayURL("story/a", 7, 101), "/drama/story%2Fa/101/");
assert.equal(pageURL("/play/story%2fa?x=a+b&x=%2b#ep%202"), "/drama/story%2fa/?x=a+b&x=%2b#ep%202");
assert.equal(videoPlayURL("movie", 9), "/series/watch/movie/");
assert.equal(categoryURL("romance", 1), "/collection/romance/");
assert.equal(allListURL("romance", 1, 2, 1, 3), "/dramas/romance/2/1/page/3/");
assert.equal(moreListURL("picks", 1, 0, "", 0, 1), "/curated/dramas/picks/");
assert.equal(moreSeriesListURL("movies", 2, 0, "", 0, 1), "/curated/series/movies/");
assert.equal(navHref("/playlet"), "/dramas/");
assert.equal(navHref("/topic/romance/"), "/collection/romance/");
assert.equal(navHref("/download-app/"), "/app/download/");
assert.equal(navHref("/home-road/"), "/return-home/");
assert.equal(navIsDownload("/app/download/", "客户端下载"), true);
assert.equal(navHasMegaMenu("/dramas/"), true);
assert.equal(listThemeSegment("/dramas/romance/2/1/"), "romance");
assert.equal(listUpdateStatus("/dramas/romance/2/1/"), 2);
assert.equal(navIsActive("/series/", "/series/watch/movie/"), false);
assert.equal(navIsActive("/dramas/", "/dramas/romance/"), true);
});
test("navigation configuration resolves both legacy and normalized collection-detail aliases without decoding slugs", () => {
for (const root of ["/topic", "/collections"]) {
assert.equal(navHref(root + "/热门?q=a"), "/collection/%E7%83%AD%E9%97%A8/?q=a");
assert.equal(navHref(root + "/story%2fa%252F1?x=a+b&x=%2b#ep%202"), "/collection/story%2fa%252F1/?x=a+b&x=%2b#ep%202");
assert.equal(navHref(root + "/page/2/"), "/collections/page/2/");
assert.equal(navHref(root + "/sort/2/"), "/collections/sort/2/");
}
});
test("SSR header exposes direct canonical URLs and no account entries", () => {
const html = render();
const links = assertPublicLinks(html);
for (const expected of ["/dramas/", "/collections/", "/rankings/", "/discover/search/", "/return-home/"])
assert.ok(links.includes(expected), expected);
assert.ok(!links.some((link) => link.startsWith("/account")), "account links removed");
assert.doesNotMatch(html, /data-login-open|hk-user-menu/);
});
test("configured header submenus expose canonical links, external link attributes and download actions", () => {
const html = render();
const links = assertPublicLinks(html);
assert.ok(links.includes("/collection/romance/"));
assert.ok(links.includes("/rankings/"));
for (const href of ["https://huangguo.com", "//partner.test/path"]) {
const anchor = [...html.matchAll(/]*>/g)].map(([tag]) => tag).find((tag) => tag.includes(`href="${href}"`));
assert.ok(anchor, href);
assert.match(anchor, /target="_blank"/);
assert.match(anchor, /rel="sponsored nofollow noopener"/);
}
assert.match(html, /]*href="https:\/\/downloads\.test\/app"[^>]*data-download-open=""/);
const toggles = [...html.matchAll(/