feat(polaris): 细分游戏资料并完善站点导航
新增游戏资料分类及九个网站链接,清理三条旧链接。 调整侧边栏提示交互,并为阿里云控制台使用本地图标。 同步更新分类、链接和交互测试。
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1791734628751" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5223" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1020.586667 361.813333c0-92.16-75.093333-167.253333-167.253334-167.253333h-266.24l23.893334 95.573333 228.693333 51.2c20.48 3.413333 37.546667 23.893333 37.546667 44.373334v245.76c0 20.48-17.066667 40.96-37.546667 44.373333l-228.693333 51.2-27.306667 92.16h266.24c92.16 0 167.253333-75.093333 167.253333-167.253333 3.413333 0 3.413333-290.133333 3.413334-290.133334zM187.733333 672.426667c-20.48-3.413333-37.546667-23.893333-37.546666-44.373334v-245.76c0-20.48 17.066667-40.96 37.546666-44.373333l228.693334-51.2 23.893333-95.573333H174.08C81.92 191.146667 6.826667 266.24 6.826667 358.4V648.533333c0 92.16 75.093333 167.253333 167.253333 167.253334h266.24l-23.893333-95.573334c0 3.413333-228.693333-47.786667-228.693334-47.786666z m215.04-211.626667h218.453334v88.746667h-218.453334v-88.746667z" fill="#ff6b01" p-id="5224"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -6,7 +6,7 @@ import { getLinksByCategory } from "@/services/links"
|
|||||||
import CategoryPage, { dynamicParams, generateStaticParams } from "./page"
|
import CategoryPage, { dynamicParams, generateStaticParams } from "./page"
|
||||||
|
|
||||||
describe("CategoryPage", () => {
|
describe("CategoryPage", () => {
|
||||||
it("为全部 7 个分类生成静态参数并关闭运行时动态参数", () => {
|
it("为全部 8 个分类生成静态参数并关闭运行时动态参数", () => {
|
||||||
expect(generateStaticParams()).toEqual([
|
expect(generateStaticParams()).toEqual([
|
||||||
{ categoryId: "ai" },
|
{ categoryId: "ai" },
|
||||||
{ categoryId: "dev" },
|
{ categoryId: "dev" },
|
||||||
@@ -14,11 +14,35 @@ describe("CategoryPage", () => {
|
|||||||
{ categoryId: "learning" },
|
{ categoryId: "learning" },
|
||||||
{ categoryId: "efficiency" },
|
{ categoryId: "efficiency" },
|
||||||
{ categoryId: "media" },
|
{ categoryId: "media" },
|
||||||
|
{ categoryId: "game-resources" },
|
||||||
{ categoryId: "life" },
|
{ categoryId: "life" },
|
||||||
])
|
])
|
||||||
expect(dynamicParams).toBe(false)
|
expect(dynamicParams).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("归类边界:游戏资料页收录宝可梦维基,娱乐媒体页不再包含", async () => {
|
||||||
|
const gamePage = await CategoryPage({
|
||||||
|
params: Promise.resolve({ categoryId: "game-resources" }),
|
||||||
|
})
|
||||||
|
render(gamePage)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByRole("heading", { level: 1, name: "游戏资料" }),
|
||||||
|
).toBeInTheDocument()
|
||||||
|
expect(
|
||||||
|
screen.getByRole("link", { name: /神奇宝贝百科/ }),
|
||||||
|
).toBeInTheDocument()
|
||||||
|
expect(
|
||||||
|
screen.getByRole("link", { name: /星露谷物语中文维基/ }),
|
||||||
|
).toBeInTheDocument()
|
||||||
|
expect(
|
||||||
|
screen.queryByRole("link", { name: /萌娘百科/ }),
|
||||||
|
).not.toBeInTheDocument()
|
||||||
|
expect(getLinksByCategory("media").map(({ id }) => id)).not.toContain(
|
||||||
|
"wiki-52poke",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it("通过 service 组合开发工具分类页", async () => {
|
it("通过 service 组合开发工具分类页", async () => {
|
||||||
const links = getLinksByCategory("dev")
|
const links = getLinksByCategory("dev")
|
||||||
const page = await CategoryPage({
|
const page = await CategoryPage({
|
||||||
|
|||||||
@@ -41,6 +41,13 @@
|
|||||||
"icon": "circle-play",
|
"icon": "circle-play",
|
||||||
"sort": 60
|
"sort": 60
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "game-resources",
|
||||||
|
"title": "游戏资料",
|
||||||
|
"description": "游戏攻略维基、资料速查与实用规划工具。",
|
||||||
|
"icon": "book-open",
|
||||||
|
"sort": 65
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "life",
|
"id": "life",
|
||||||
"title": "生活服务",
|
"title": "生活服务",
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ const hasUniqueValues = (values: string[]) =>
|
|||||||
new Set(values).size === values.length
|
new Set(values).size === values.length
|
||||||
|
|
||||||
describe("Polaris 静态数据", () => {
|
describe("Polaris 静态数据", () => {
|
||||||
it("包含 7 个唯一且结构完整的分类", () => {
|
it("包含 8 个唯一且结构完整的分类", () => {
|
||||||
expect(categories).toHaveLength(7)
|
expect(categories).toHaveLength(8)
|
||||||
expect(hasUniqueValues(categories.map(({ id }) => id))).toBe(true)
|
expect(hasUniqueValues(categories.map(({ id }) => id))).toBe(true)
|
||||||
|
expect(hasUniqueValues(categories.map(({ sort }) => String(sort)))).toBe(
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
|
||||||
for (const category of categories) {
|
for (const category of categories) {
|
||||||
expect(category).toEqual({
|
expect(category).toEqual({
|
||||||
@@ -27,9 +30,9 @@ describe("Polaris 静态数据", () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it("包含 45 条合法链接且分类引用均存在", () => {
|
it("包含 51 条合法链接且分类引用均存在", () => {
|
||||||
const categoryIds = new Set(categories.map(({ id }) => id))
|
const categoryIds = new Set(categories.map(({ id }) => id))
|
||||||
expect(links).toHaveLength(45)
|
expect(links).toHaveLength(51)
|
||||||
expect(hasUniqueValues(links.map(({ id }) => id))).toBe(true)
|
expect(hasUniqueValues(links.map(({ id }) => id))).toBe(true)
|
||||||
|
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
@@ -115,4 +118,134 @@ describe("Polaris 静态数据", () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("归类边界回归", () => {
|
||||||
|
const linkIdsByCategory = (categoryId: string) =>
|
||||||
|
links
|
||||||
|
.filter((link) => link.categoryId === categoryId)
|
||||||
|
.map(({ id }) => id)
|
||||||
|
.sort()
|
||||||
|
|
||||||
|
it("游戏维基与攻略工具归入 game-resources", () => {
|
||||||
|
expect(linkIdsByCategory("game-resources")).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
"wiki-52poke",
|
||||||
|
"wiki-blhx",
|
||||||
|
"wiki-fgo",
|
||||||
|
"wiki-stardew",
|
||||||
|
"wiki-terraria",
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("娱乐媒体保留影音社区与 ACG 百科,不混入游戏资料", () => {
|
||||||
|
const mediaIds = linkIdsByCategory("media")
|
||||||
|
|
||||||
|
expect(mediaIds).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
"youtube",
|
||||||
|
"bilibili",
|
||||||
|
"spotify",
|
||||||
|
"nexusmods",
|
||||||
|
"pokemon-showdown",
|
||||||
|
"expreview",
|
||||||
|
"chairo",
|
||||||
|
"wiki-moegirl",
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
for (const gameId of [
|
||||||
|
"wiki-52poke",
|
||||||
|
"wiki-blhx",
|
||||||
|
"wiki-fgo",
|
||||||
|
"wiki-stardew",
|
||||||
|
"wiki-terraria",
|
||||||
|
]) {
|
||||||
|
expect(mediaIds).not.toContain(gameId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Nexus Mods 与 Pokemon Showdown 等实测工具仍留在娱乐媒体", () => {
|
||||||
|
const mediaIds = linkIdsByCategory("media")
|
||||||
|
|
||||||
|
expect(mediaIds).toContain("nexusmods")
|
||||||
|
expect(mediaIds).toContain("pokemon-showdown")
|
||||||
|
expect(linkIdsByCategory("game-resources")).not.toContain("nexusmods")
|
||||||
|
expect(linkIdsByCategory("game-resources")).not.toContain(
|
||||||
|
"pokemon-showdown",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("新增九条链接回归", () => {
|
||||||
|
const expectedNewLinks = [
|
||||||
|
{
|
||||||
|
id: "kzo",
|
||||||
|
url: "https://kzo.moe",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "manhuagui",
|
||||||
|
url: "https://www.manhuagui.com",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "linovelib",
|
||||||
|
url: "https://www.linovelib.com",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "steam",
|
||||||
|
url: "https://store.steampowered.com",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "tieba",
|
||||||
|
url: "https://tieba.baidu.com",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "manga-bilibili",
|
||||||
|
url: "https://manga.bilibili.com",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "zhihu",
|
||||||
|
url: "https://www.zhihu.com",
|
||||||
|
categoryId: "media",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "pixiv",
|
||||||
|
url: "https://www.pixiv.net",
|
||||||
|
categoryId: "design",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "aliyun-unified-console",
|
||||||
|
url: "https://home.console.aliyun.com",
|
||||||
|
categoryId: "efficiency",
|
||||||
|
},
|
||||||
|
] as const
|
||||||
|
|
||||||
|
it("九条新链接全部存在且总数为 51", () => {
|
||||||
|
expect(links).toHaveLength(51)
|
||||||
|
expect(
|
||||||
|
expectedNewLinks.every(({ id }) =>
|
||||||
|
links.some((link) => link.id === id),
|
||||||
|
),
|
||||||
|
).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each(expectedNewLinks)(
|
||||||
|
"$id 归入 $categoryId 且 URL 正确",
|
||||||
|
(expected) => {
|
||||||
|
const link = links.find(({ id }) => id === expected.id)
|
||||||
|
|
||||||
|
expect(link).toBeDefined()
|
||||||
|
expect(link).toMatchObject({
|
||||||
|
url: expected.url,
|
||||||
|
categoryId: expected.categoryId,
|
||||||
|
pinned: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -266,47 +266,27 @@
|
|||||||
"title": "神奇宝贝百科",
|
"title": "神奇宝贝百科",
|
||||||
"description": "宝可梦中文资料维基",
|
"description": "宝可梦中文资料维基",
|
||||||
"url": "https://wiki.52poke.com/wiki/%E4%B8%BB%E9%A1%B5",
|
"url": "https://wiki.52poke.com/wiki/%E4%B8%BB%E9%A1%B5",
|
||||||
"categoryId": "media",
|
"categoryId": "game-resources",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["宝可梦", "口袋妖怪", "攻略", "资料"],
|
"keywords": ["宝可梦", "口袋妖怪", "攻略", "资料"],
|
||||||
"sort": 80
|
"sort": 80
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "wiki-52poke-typechart",
|
|
||||||
"title": "宝可梦属性相克表",
|
|
||||||
"description": "宝可梦全属性克制关系速查",
|
|
||||||
"url": "https://wiki.52poke.com/wiki/%E5%B1%9E%E6%80%A7%E7%9B%B8%E5%85%8B%E8%A1%A8",
|
|
||||||
"categoryId": "media",
|
|
||||||
"pinned": false,
|
|
||||||
"keywords": ["宝可梦", "属性", "相克", "速查"],
|
|
||||||
"sort": 90
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "wiki-blhx",
|
"id": "wiki-blhx",
|
||||||
"title": "碧蓝航线WIKI",
|
"title": "碧蓝航线WIKI",
|
||||||
"description": "碧蓝航线官方中文百科",
|
"description": "碧蓝航线官方中文百科",
|
||||||
"url": "https://wiki.biligame.com/blhx/%E9%A6%96%E9%A1%B5",
|
"url": "https://wiki.biligame.com/blhx/%E9%A6%96%E9%A1%B5",
|
||||||
"categoryId": "media",
|
"categoryId": "game-resources",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["碧蓝航线", "手游", "攻略", "wiki"],
|
"keywords": ["碧蓝航线", "手游", "攻略", "wiki"],
|
||||||
"sort": 100
|
"sort": 100
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "wiki-blhx-boss",
|
|
||||||
"title": "碧蓝航线月度BOSS解析",
|
|
||||||
"description": "大型作战月度 BOSS 攻略解析",
|
|
||||||
"url": "https://wiki.biligame.com/blhx/%E5%A4%A7%E5%9E%8B%E4%BD%9C%E6%88%98%E6%9C%88%E5%BA%A6BOSS%E8%A7%A3%E6%9E%90",
|
|
||||||
"categoryId": "media",
|
|
||||||
"pinned": false,
|
|
||||||
"keywords": ["碧蓝航线", "boss", "攻略", "大型作战"],
|
|
||||||
"sort": 110
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "wiki-fgo",
|
"id": "wiki-fgo",
|
||||||
"title": "Mooncell",
|
"title": "Mooncell",
|
||||||
"description": "FGO 中文维基与攻略资料站",
|
"description": "FGO 中文维基与攻略资料站",
|
||||||
"url": "https://fgo.wiki/w/%E9%A6%96%E9%A1%B5",
|
"url": "https://fgo.wiki/w/%E9%A6%96%E9%A1%B5",
|
||||||
"categoryId": "media",
|
"categoryId": "game-resources",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["fgo", "mooncell", "从者", "攻略"],
|
"keywords": ["fgo", "mooncell", "从者", "攻略"],
|
||||||
"sort": 120
|
"sort": 120
|
||||||
@@ -316,7 +296,7 @@
|
|||||||
"title": "星露谷物语中文维基",
|
"title": "星露谷物语中文维基",
|
||||||
"description": "星露谷物语官方中文资料维基",
|
"description": "星露谷物语官方中文资料维基",
|
||||||
"url": "https://zh.stardewvalleywiki.com",
|
"url": "https://zh.stardewvalleywiki.com",
|
||||||
"categoryId": "media",
|
"categoryId": "game-resources",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["星露谷物语", "攻略", "作物", "wiki"],
|
"keywords": ["星露谷物语", "攻略", "作物", "wiki"],
|
||||||
"sort": 130
|
"sort": 130
|
||||||
@@ -326,7 +306,7 @@
|
|||||||
"title": "泰拉瑞亚中文维基",
|
"title": "泰拉瑞亚中文维基",
|
||||||
"description": "泰拉瑞亚官方中文百科",
|
"description": "泰拉瑞亚官方中文百科",
|
||||||
"url": "https://terraria.wiki.gg/zh",
|
"url": "https://terraria.wiki.gg/zh",
|
||||||
"categoryId": "media",
|
"categoryId": "game-resources",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["泰拉瑞亚", "攻略", "物品", "wiki"],
|
"keywords": ["泰拉瑞亚", "攻略", "物品", "wiki"],
|
||||||
"sort": 140
|
"sort": 140
|
||||||
@@ -341,16 +321,6 @@
|
|||||||
"keywords": ["动漫", "acg", "百科", "二次元"],
|
"keywords": ["动漫", "acg", "百科", "二次元"],
|
||||||
"sort": 150
|
"sort": 150
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "farmgamehub",
|
|
||||||
"title": "星露谷洒水器规划器",
|
|
||||||
"description": "星露谷物语洒水器布局可视化工具",
|
|
||||||
"url": "https://www.farmgamehub.com/zh/tools/stardew-sprinklers",
|
|
||||||
"categoryId": "media",
|
|
||||||
"pinned": false,
|
|
||||||
"keywords": ["星露谷物语", "洒水器", "布局", "工具"],
|
|
||||||
"sort": 160
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "iodraw",
|
"id": "iodraw",
|
||||||
"title": "iodraw",
|
"title": "iodraw",
|
||||||
@@ -406,7 +376,8 @@
|
|||||||
"id": "aliyun-console",
|
"id": "aliyun-console",
|
||||||
"title": "阿里云轻量控制台",
|
"title": "阿里云轻量控制台",
|
||||||
"description": "阿里云轻量应用服务器控制台",
|
"description": "阿里云轻量应用服务器控制台",
|
||||||
"url": "https://swas.console.aliyun.com",
|
"url": "https://console.aliyun.com",
|
||||||
|
"icon": "local:ali-cloud",
|
||||||
"categoryId": "efficiency",
|
"categoryId": "efficiency",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["阿里云", "控制台", "轻量服务器", "云服务"],
|
"keywords": ["阿里云", "控制台", "轻量服务器", "云服务"],
|
||||||
@@ -472,5 +443,96 @@
|
|||||||
"pinned": false,
|
"pinned": false,
|
||||||
"keywords": ["地图", "导航", "出行", "路线"],
|
"keywords": ["地图", "导航", "出行", "路线"],
|
||||||
"sort": 10
|
"sort": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kzo",
|
||||||
|
"title": "Kmoe 漫画",
|
||||||
|
"description": "Kindle/EPUB 漫画下载与推送",
|
||||||
|
"url": "https://kzo.moe",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["漫画", "kindle", "epub", "推送"],
|
||||||
|
"sort": 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "manhuagui",
|
||||||
|
"title": "漫画柜",
|
||||||
|
"description": "在线漫画阅读站点",
|
||||||
|
"url": "https://www.manhuagui.com",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["漫画", "在线阅读", "动漫"],
|
||||||
|
"sort": 170
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "linovelib",
|
||||||
|
"title": "轻小说文库",
|
||||||
|
"description": "在线轻小说阅读站点",
|
||||||
|
"url": "https://www.linovelib.com",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["轻小说", "在线阅读", "文库"],
|
||||||
|
"sort": 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "steam",
|
||||||
|
"title": "Steam",
|
||||||
|
"description": "PC 游戏数字发行商店",
|
||||||
|
"url": "https://store.steampowered.com",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["游戏", "商店", "平台"],
|
||||||
|
"sort": 190
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tieba",
|
||||||
|
"title": "百度贴吧",
|
||||||
|
"description": "百度旗下主题兴趣社区",
|
||||||
|
"url": "https://tieba.baidu.com",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["贴吧", "论坛", "社区", "百度"],
|
||||||
|
"sort": 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "manga-bilibili",
|
||||||
|
"title": "哔哩哔哩漫画",
|
||||||
|
"description": "哔哩哔哩正版漫画平台",
|
||||||
|
"url": "https://manga.bilibili.com",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["漫画", "哔哩哔哩", "正版", "阅读"],
|
||||||
|
"sort": 210
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zhihu",
|
||||||
|
"title": "知乎",
|
||||||
|
"description": "中文问答社区",
|
||||||
|
"url": "https://www.zhihu.com",
|
||||||
|
"categoryId": "media",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["问答", "社区", "知识"],
|
||||||
|
"sort": 220
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "pixiv",
|
||||||
|
"title": "pixiv",
|
||||||
|
"description": "插画作品分享社区",
|
||||||
|
"url": "https://www.pixiv.net",
|
||||||
|
"categoryId": "design",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["插画", "绘画", "灵感", "二次元"],
|
||||||
|
"sort": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aliyun-unified-console",
|
||||||
|
"title": "阿里云统一控制台",
|
||||||
|
"description": "阿里云产品统一管理控制台",
|
||||||
|
"url": "https://home.console.aliyun.com",
|
||||||
|
"icon": "local:ali-cloud",
|
||||||
|
"categoryId": "efficiency",
|
||||||
|
"pinned": false,
|
||||||
|
"keywords": ["阿里云", "控制台", "云服务", "管理"],
|
||||||
|
"sort": 100
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ describe("CategoryContent", () => {
|
|||||||
"learning",
|
"learning",
|
||||||
"efficiency",
|
"efficiency",
|
||||||
"media",
|
"media",
|
||||||
|
"game-resources",
|
||||||
"life",
|
"life",
|
||||||
] as const)("%s 分类展示服务提供的数量", (categoryId) => {
|
] as const)("%s 分类展示服务提供的数量", (categoryId) => {
|
||||||
const category = getCategoryById(categoryId)
|
const category = getCategoryById(categoryId)
|
||||||
@@ -82,4 +83,24 @@ describe("CategoryContent", () => {
|
|||||||
|
|
||||||
expect(screen.getByText(`共 ${links.length} 个`)).toBeInTheDocument()
|
expect(screen.getByText(`共 ${links.length} 个`)).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("归类边界:游戏资料面板只渲染 5 个游戏维基卡片", () => {
|
||||||
|
const category = getCategoryById("game-resources")
|
||||||
|
if (!category) throw new Error("测试数据缺少 game-resources 分类")
|
||||||
|
const links = getLinksByCategory(category.id)
|
||||||
|
|
||||||
|
render(<CategoryContent category={category} links={links} />)
|
||||||
|
|
||||||
|
expect(links).toHaveLength(5)
|
||||||
|
const toolLinks = screen
|
||||||
|
.getByRole("list", { name: "工具列表" })
|
||||||
|
.querySelectorAll("a")
|
||||||
|
expect(toolLinks).toHaveLength(5)
|
||||||
|
expect(
|
||||||
|
screen.queryByRole("link", { name: /萌娘百科/ }),
|
||||||
|
).not.toBeInTheDocument()
|
||||||
|
expect(
|
||||||
|
screen.queryByRole("link", { name: /Nexus Mods/ }),
|
||||||
|
).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react"
|
import { fireEvent, render, screen, waitFor } from "@testing-library/react"
|
||||||
|
import userEvent from "@testing-library/user-event"
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
|
||||||
|
|
||||||
import type { Category } from "@/types/navigation"
|
import type { Category } from "@/types/navigation"
|
||||||
@@ -9,9 +10,18 @@ const categories: Category[] = [
|
|||||||
{ id: "dev", title: "开发工具", description: "开发", icon: "code", sort: 10 },
|
{ id: "dev", title: "开发工具", description: "开发", icon: "code", sort: 10 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class ResizeObserverStub {
|
||||||
|
observe() {}
|
||||||
|
unobserve() {}
|
||||||
|
disconnect() {}
|
||||||
|
}
|
||||||
|
|
||||||
describe("AppShell", () => {
|
describe("AppShell", () => {
|
||||||
beforeEach(() => window.localStorage.clear())
|
beforeEach(() => window.localStorage.clear())
|
||||||
afterEach(() => vi.restoreAllMocks())
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks()
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
it("切换侧栏并持久化状态", () => {
|
it("切换侧栏并持久化状态", () => {
|
||||||
render(
|
render(
|
||||||
@@ -198,4 +208,67 @@ describe("AppShell", () => {
|
|||||||
"page",
|
"page",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("展开时分类文字可见,悬停或聚焦不显示提示", async () => {
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(
|
||||||
|
<AppShell
|
||||||
|
categories={categories}
|
||||||
|
siteName="Polaris"
|
||||||
|
defaultCollapsed={false}
|
||||||
|
>
|
||||||
|
<main>首页内容</main>
|
||||||
|
</AppShell>,
|
||||||
|
)
|
||||||
|
|
||||||
|
const link = screen.getByRole("link", { name: "开发工具" })
|
||||||
|
expect(link.querySelector(".sidebar__label")).not.toHaveClass("sr-only")
|
||||||
|
await user.hover(link)
|
||||||
|
expect(link).not.toHaveAttribute("data-state")
|
||||||
|
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument()
|
||||||
|
|
||||||
|
link.focus()
|
||||||
|
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("收起时悬停分类图标显示分类名提示", async () => {
|
||||||
|
vi.stubGlobal("ResizeObserver", ResizeObserverStub)
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(
|
||||||
|
<AppShell
|
||||||
|
categories={categories}
|
||||||
|
siteName="Polaris"
|
||||||
|
defaultCollapsed={true}
|
||||||
|
>
|
||||||
|
<main>首页内容</main>
|
||||||
|
</AppShell>,
|
||||||
|
)
|
||||||
|
|
||||||
|
const link = screen.getByRole("link", { name: "开发工具" })
|
||||||
|
expect(link.querySelector(".sidebar__label")).toHaveClass("sr-only")
|
||||||
|
await user.hover(link)
|
||||||
|
expect(await screen.findByRole("tooltip")).toHaveTextContent("开发工具")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("收起时键盘聚焦分类图标显示分类名提示", async () => {
|
||||||
|
vi.stubGlobal("ResizeObserver", ResizeObserverStub)
|
||||||
|
const user = userEvent.setup()
|
||||||
|
render(
|
||||||
|
<AppShell
|
||||||
|
categories={categories}
|
||||||
|
siteName="Polaris"
|
||||||
|
defaultCollapsed={true}
|
||||||
|
>
|
||||||
|
<main>首页内容</main>
|
||||||
|
</AppShell>,
|
||||||
|
)
|
||||||
|
|
||||||
|
await user.tab()
|
||||||
|
await user.tab()
|
||||||
|
await user.tab()
|
||||||
|
await user.tab()
|
||||||
|
const link = screen.getByRole("link", { name: "开发工具" })
|
||||||
|
expect(link).toHaveFocus()
|
||||||
|
expect(await screen.findByRole("tooltip")).toHaveTextContent("开发工具")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -81,28 +81,30 @@ export function Sidebar({
|
|||||||
<div className="sidebar__categories">
|
<div className="sidebar__categories">
|
||||||
{categories.map((category) => {
|
{categories.map((category) => {
|
||||||
const isActive = category.id === activeCategoryId
|
const isActive = category.id === activeCategoryId
|
||||||
|
const categoryLink = (
|
||||||
|
<Link
|
||||||
|
key={category.id}
|
||||||
|
className={cn(
|
||||||
|
"sidebar__nav-item",
|
||||||
|
isActive && "sidebar__nav-item--active",
|
||||||
|
)}
|
||||||
|
href={`/categories/${category.id}`}
|
||||||
|
aria-current={isActive ? "page" : undefined}
|
||||||
|
>
|
||||||
|
<CategoryIcon name={category.icon} />
|
||||||
|
<span className={cn("sidebar__label", collapsed && "sr-only")}>
|
||||||
|
{category.title}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return collapsed ? (
|
||||||
<Tooltip key={category.id}>
|
<Tooltip key={category.id}>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>{categoryLink}</TooltipTrigger>
|
||||||
<Link
|
|
||||||
className={cn(
|
|
||||||
"sidebar__nav-item",
|
|
||||||
isActive && "sidebar__nav-item--active",
|
|
||||||
)}
|
|
||||||
href={`/categories/${category.id}`}
|
|
||||||
aria-current={isActive ? "page" : undefined}
|
|
||||||
>
|
|
||||||
<CategoryIcon name={category.icon} />
|
|
||||||
<span
|
|
||||||
className={cn("sidebar__label", collapsed && "sr-only")}
|
|
||||||
>
|
|
||||||
{category.title}
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent side="right">{category.title}</TooltipContent>
|
<TooltipContent side="right">{category.title}</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
categoryLink
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ describe("静态数据 service", () => {
|
|||||||
"learning",
|
"learning",
|
||||||
"efficiency",
|
"efficiency",
|
||||||
"media",
|
"media",
|
||||||
|
"game-resources",
|
||||||
"life",
|
"life",
|
||||||
])
|
])
|
||||||
expect(first).not.toBe(second)
|
expect(first).not.toBe(second)
|
||||||
@@ -55,6 +56,7 @@ describe("静态数据 service", () => {
|
|||||||
"iconfont",
|
"iconfont",
|
||||||
"haowallpaper",
|
"haowallpaper",
|
||||||
"iodraw",
|
"iodraw",
|
||||||
|
"pixiv",
|
||||||
])
|
])
|
||||||
expect(getLinksByCategory("life").map(({ id }) => id)).toEqual(["amap"])
|
expect(getLinksByCategory("life").map(({ id }) => id)).toEqual(["amap"])
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user