import assert from "node:assert/strict";
import test from "node:test";
import { renderToStaticMarkup } from "react-dom/server";
import {
DramaCard,
PlayRecommendationCard,
SeriesCard,
} from "../src/components/catalog/Cards";
import { Pagination } from "../src/components/catalog/Pagination";
import { PromoGrid } from "../src/components/catalog/Promotions";
import {
CatalogGrid,
ListPage,
SeriesPage,
} from "../src/features/catalog/BrowsePages";
import {
allListURL,
array,
cardTags,
moreListURL,
moreSeriesListURL,
searchResultsURL,
seriesListURL,
tagPageURL,
topicDetailURL,
} from "../src/features/catalog/model";
const item = {
id: 7,
slug: "都市 剧",
playName: "作品名",
title: "备用标题",
cover: "/static/brand/header.svg",
totalEpisode: 8,
updateStatus: 1,
isFeatured: true,
tagIds: [2],
tagNames: ["爱情"],
tagSlugs: ["romance"],
themeIds: [3],
themeNames: ["爱情", "都市"],
themeSlugs: ["love", "city"],
};
const ads = [
{
id: 1,
images: "/static/brand/header.svg",
link: "https://promo.test/",
title: "推荐",
},
];
test("React card variants preserve watch URLs, episode gates, badges and linked deduplicated tags", () => {
const card = renderToStaticMarkup();
assert.match(card, /class="hk-drama-card hk-drama-card--list"/);
assert.match(
card,
/href="\/drama\/都市%20剧\/"|href="\/drama\/%E9%83%BD%E5%B8%82%20%E5%89%A7\/"/,
);
assert.match(
card,
/
连载 · 8 集<\/span>/,
);
assert.doesNotMatch(card, /hk-drama-card__ep"/);
assert.match(card, /hk-badge hk-badge--hot/);
assert.match(card, /href="\/tags\/romance\/"/);
assert.deepEqual(
cardTags(item).map((tag) => tag.Name),
["爱情", "都市"],
);
const recommendation = renderToStaticMarkup(
,
);
assert.match(recommendation, /hk-drama-card hk-drama-card--play/);
assert.match(recommendation, /hk-drama-card__meta-ep" data-status="serial">连载 · 8 集);
assert.doesNotMatch(recommendation, /hk-badge--hot/);
const video = renderToStaticMarkup(
,
);
assert.match(video, /href="\/series\/watch\/movie\/"/);
assert.match(video, /全 12 集/);
assert.match(video, /动画/);
});
test("React list advertising keeps independent desktop and mobile row positions and clone attribution", () => {
const items = array(
Array.from({ length: 25 }, (_, index) => ({ ...item, id: index + 1 })),
);
const grid = renderToStaticMarkup();
assert.equal((grid.match(/class="hk-drama-card hk-drama-card--list"/g) || []).length, 25);
assert.equal((grid.match(/class="hk-drama-browse-mid-promo hk-desktop-only"/g) || []).length, 2);
assert.equal((grid.match(/class="hk-drama-browse-mid-promo hk-mobile-only"/g) || []).length, 4);
const videoGrid = renderToStaticMarkup(
,
);
assert.equal(
(videoGrid.match(/class="hk-series-list-promo hk-desktop-only"/g) || []).length,
1,
);
assert.equal(
(videoGrid.match(/class="hk-series-list-promo hk-mobile-only"/g) || []).length,
3,
);
const promo = renderToStaticMarkup();
assert.equal((promo.match(/rel="sponsored nofollow noopener"/g) || []).length, 2);
assert.equal((promo.match(/tabindex="-1"/g) || []).length, 1);
});
test("React filter and pagination links preserve the source path-only canonical route contracts", () => {
assert.equal(allListURL("", 0, 0, 1, 1), "/dramas/");
assert.equal(
allListURL("都市", 3, 2, 3, 2),
"/dramas/%E9%83%BD%E5%B8%82/2/3/page/2/",
);
assert.equal(seriesListURL(2, 4, 3, 2), "/series/anime/4/3/page/2/");
assert.equal(moreListURL("featured", 1, 0, "", 0, 1), "/curated/dramas/featured/");
assert.equal(
moreSeriesListURL("", 3, 1, "city", 0, 2),
"/curated/series/3/1/city/page/2/",
);
assert.equal(tagPageURL("romance", 1, 2, 1), "/tags/romance/sort/2/");
assert.equal(
topicDetailURL("city", 1, 3, 2),
"/collection/city/sort/3/page/2/",
);
assert.equal(searchResultsURL("a/b"), "/search/a%2Fb/");
const html = renderToStaticMarkup(
,
);
assert.match(html, /hk-pagination__btn--prev hk-is-disabled/);
assert.match(html, /aria-current="page"/);
assert.match(html, /href="\/dramas\/all\/0\/1\/page\/2\/"/);
assert.match(html, /hk-pagination__ellipsis/);
assert.match(html, /共 3 页/);
const list = renderToStaticMarkup(
,
);
assert.match(list, /href="\/dramas\/city\/2\/3\/"/);
assert.match(list, /暂无短剧/);
const series = renderToStaticMarkup(
,
);
assert.match(series, /href="\/series\/anime\/4\/1\/"/);
assert.match(series, /暂无剧集/);
});