P1-6 useStyleLearn/useKimiOauth 修 stale-closure 依赖。 P1-7 CommandPalette/Drawer 加 focus trap(新 lib/a11y/focusTrap)。 P1-8 SSE 解析与 server.ts 去 as 强转改类型守卫/运行时校验。 P2 删冗余强转、开 noUncheckedIndexedAccess、Toast 清理+稳定 key、列表 key 稳定化、 rel=noopener、useMemo 大文本、ConflictCard role=group、useInjection 加锁、 client.test 真断言。 codegen 重生成 schema.d.ts + 消费 DimensionEntry/ReviewConflictView 强类型。
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import type { SkillView } from "@/lib/api/types";
|
|
import { groupByScope, scopeLabel, tierLabel } from "./skills";
|
|
|
|
const skill = (over: Partial<SkillView>): SkillView => ({
|
|
name: "x",
|
|
scope: "builtin",
|
|
tier: "analyst",
|
|
...over,
|
|
});
|
|
|
|
describe("scopeLabel / tierLabel", () => {
|
|
it("maps known values, passes through unknown", () => {
|
|
expect(scopeLabel("builtin")).toBe("内置");
|
|
expect(scopeLabel("mystery")).toBe("mystery");
|
|
expect(tierLabel("writer")).toBe("写手");
|
|
expect(tierLabel("xl")).toBe("xl");
|
|
});
|
|
});
|
|
|
|
describe("groupByScope", () => {
|
|
it("groups by scope in first-seen order, preserves within-group order", () => {
|
|
const skills: SkillView[] = [
|
|
skill({ name: "a", scope: "builtin" }),
|
|
skill({ name: "b", scope: "custom" }),
|
|
skill({ name: "c", scope: "builtin" }),
|
|
];
|
|
const groups = groupByScope(skills);
|
|
expect(groups.map((g) => g.scope)).toEqual(["builtin", "custom"]);
|
|
expect(groups[0]?.skills.map((s) => s.name)).toEqual(["a", "c"]);
|
|
expect(groups[1]?.skills.map((s) => s.name)).toEqual(["b"]);
|
|
});
|
|
|
|
it("handles undefined", () => {
|
|
expect(groupByScope(undefined)).toEqual([]);
|
|
});
|
|
});
|