Files
lab/ts/web/nextjs/polaris/src/data/data.test.ts
T
labmem e37cf9936e feat(polaris): import bookmarks and refine category scrolling
- 导入 29 条精选公开书签,排除重复与敏感入口
- 将滚动限制在分类页内层卡片区域,并适配窄屏
- 更新数据与页面测试
2026-10-08 19:49:30 +08:00

119 lines
4.2 KiB
TypeScript

import { describe, expect, it } from "vitest"
import categories from "@/data/categories.json"
import links from "@/data/links.json"
import settings from "@/data/settings.json"
import { SEARCH_PROVIDERS } from "@/types/search"
const hasUniqueValues = (values: string[]) =>
new Set(values).size === values.length
describe("Polaris 静态数据", () => {
it("包含 7 个唯一且结构完整的分类", () => {
expect(categories).toHaveLength(7)
expect(hasUniqueValues(categories.map(({ id }) => id))).toBe(true)
for (const category of categories) {
expect(category).toEqual({
id: expect.any(String),
title: expect.any(String),
description: expect.any(String),
icon: expect.any(String),
sort: expect.any(Number),
})
expect(category.id).not.toBe("")
expect(category.title).not.toBe("")
expect(Number.isFinite(category.sort)).toBe(true)
}
})
it("包含 45 条合法链接且分类引用均存在", () => {
const categoryIds = new Set(categories.map(({ id }) => id))
expect(links).toHaveLength(45)
expect(hasUniqueValues(links.map(({ id }) => id))).toBe(true)
for (const link of links) {
expect(link.id).toEqual(expect.any(String))
expect(link.title).toEqual(expect.any(String))
expect(link.description).toEqual(expect.any(String))
expect(link.url).toEqual(expect.any(String))
expect(link.categoryId).toEqual(expect.any(String))
expect(link.pinned).toEqual(expect.any(Boolean))
expect(link.keywords).toEqual(expect.any(Array))
expect(link.sort).toEqual(expect.any(Number))
expect(link.id).not.toBe("")
expect(link.title).not.toBe("")
expect(() => new URL(link.url)).not.toThrow()
// 跨分类常用链接仍必须归属于真实分类,避免未来 API 出现悬空外键。
expect(categoryIds.has(link.categoryId)).toBe(true)
expect(
link.keywords.every((keyword) => typeof keyword === "string"),
).toBe(true)
expect(Number.isFinite(link.sort)).toBe(true)
if (link.icon !== undefined) expect(typeof link.icon).toBe("string")
if (!link.pinned) expect(link.pinnedSort).toBeUndefined()
}
})
it("6 条常用链接拥有唯一 pinnedSort", () => {
const pinned = links.filter(({ pinned }) => pinned)
const pinnedSorts = pinned.map(({ pinnedSort }) => pinnedSort)
expect(pinned).toHaveLength(6)
expect(pinnedSorts.every(Number.isFinite)).toBe(true)
expect(new Set(pinnedSorts).size).toBe(6)
})
it("设置包含完整且合法的嵌套契约", () => {
expect(settings).toEqual({
siteName: "Polaris",
theme: "light-glass",
search: {
defaultProvider: "google",
enabledProviders: [...SEARCH_PROVIDERS],
},
background: {
type: "gradient",
url: null,
blur: expect.any(Number),
overlay: expect.any(Number),
},
sidebar: {
defaultCollapsed: expect.any(Boolean),
},
})
expect(SEARCH_PROVIDERS).toContain(settings.search.defaultProvider)
expect(Number.isFinite(settings.background.blur)).toBe(true)
expect(Number.isFinite(settings.background.overlay)).toBe(true)
})
describe("导入链接卫生检查", () => {
const normalizeUrl = (url: string) => url.replace(/\/+$/, "")
it("全部链接 URL 唯一(忽略末尾斜杠)", () => {
const urls = links.map(({ url }) => normalizeUrl(url))
expect(hasUniqueValues(urls)).toBe(true)
})
it("不包含本地或内网地址", () => {
for (const link of links) {
const { hostname } = new URL(link.url)
expect(hostname).toMatch(/^[\w.-]+$/)
expect(hostname).not.toBe("localhost")
expect(hostname).not.toMatch(/\.(local|lan|internal)$/)
expect(hostname).not.toMatch(
/^(127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|169\.254\.|0\.0\.0\.0)/,
)
}
})
it("不携带查询参数或片段,防止 sid/jumpuin 等会话标识混入", () => {
for (const link of links) {
const url = new URL(link.url)
expect([...url.searchParams.keys()]).toEqual([])
expect(url.hash).toBe("")
}
})
})
})