I-2, M-4..M-8, M-11, M-13, M-16, M-18, T7.3, M-1..M-3, M-17. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
3.5 KiB
TypeScript
66 lines
3.5 KiB
TypeScript
import { readFileSync } from "node:fs";
|
||
import { join } from "node:path";
|
||
import { describe, expect, it } from "vitest";
|
||
import type { BoardSnapshot } from "../../api/types.ts";
|
||
import { canon } from "../../test/canon.ts";
|
||
import { dictsFromSettings } from "../dicts.ts";
|
||
import settings from "../__fixtures__/settings.json";
|
||
import scenarios from "../__fixtures__/scenarios.json";
|
||
import { fromHub } from "../model/fromHub.ts";
|
||
import { filtersOf } from "../../test/boardScenarios.ts";
|
||
import { noFilters } from "../types.ts";
|
||
import { initialSprints, initialWho, sprintItems, whoItems } from "./facets.ts";
|
||
import { emptyReason, computeVisible } from "./visible.ts";
|
||
|
||
const fx = (name: string) => readFileSync(join(import.meta.dirname, "..", "__fixtures__", name), "utf8");
|
||
const golden = JSON.parse(fx("hub-basic.expected.json"));
|
||
const { dicts } = dictsFromSettings(settings);
|
||
const model = fromHub(JSON.parse(fx("hub-basic.board.json")) as BoardSnapshot, dicts);
|
||
const TODAY = "2026-10-14";
|
||
|
||
type Sc = { name: string; filters: Record<string, unknown>; laneOrder?: string[] };
|
||
|
||
describe("выборка = links.html@3931a88", () => {
|
||
for (const sc of scenarios as Sc[]) {
|
||
it(`computeVisible: ${sc.name}`, () => {
|
||
const f = filtersOf(sc);
|
||
const vis = computeVisible(model, f, sc.laneOrder ?? [], TODAY);
|
||
const g = golden.scenarios[sc.name];
|
||
expect(canon(vis)).toEqual(g.visible);
|
||
expect(vis.nodes.length ? null : emptyReason(model, vis, f)).toEqual(g.emptyReason);
|
||
});
|
||
}
|
||
|
||
it("пустое зеркало — своя причина", () => {
|
||
const empty = fromHub(JSON.parse(fx("hub-empty.board.json")) as BoardSnapshot, dicts);
|
||
const vis = computeVisible(empty, noFilters(), [], TODAY);
|
||
expect(emptyReason(empty, vis, noFilters())).toBe(JSON.parse(fx("hub-empty.expected.json")).scenario.emptyReason);
|
||
});
|
||
|
||
it("счётчики и начальный выбор спринтов и исполнителей", () => {
|
||
// порядок как в старой странице: сначала спринты (счётчики без фильтров), затем исполнители — уже с выбранными спринтами
|
||
const check = (remembered: unknown, g: { sprintItems: unknown; whoItems: unknown; sprints: unknown; who: unknown }) => {
|
||
const f = noFilters();
|
||
expect(canon(sprintItems(model, f).items)).toEqual(g.sprintItems);
|
||
f.sprints = initialSprints(model, f, remembered);
|
||
expect(canon(f.sprints)).toEqual(g.sprints);
|
||
expect(canon(whoItems(model, f).items)).toEqual(g.whoItems);
|
||
expect(canon(initialWho(model, f, []))).toEqual(g.who);
|
||
};
|
||
check(null, golden.facets.default);
|
||
check([], golden.facets.rememberedAll);
|
||
check(["AWPCA_Спринт 3", "нет такого"], golden.facets.rememberedSome);
|
||
});
|
||
|
||
it("initialWho: из запомненного остаются только исполнители, которые есть на доске", () => {
|
||
const real = "Иванов Иван Иванович";
|
||
expect(canon(initialWho(model, noFilters(), [real, "нет такого"]))).toEqual([real]);
|
||
});
|
||
|
||
it("initialWho: все задачи без исполнителя — выбор пуст, даже если запомнен пустой ключ", () => {
|
||
const snap = JSON.parse(fx("hub-basic.board.json")) as BoardSnapshot;
|
||
const bare = fromHub({ ...snap, issues: snap.issues.map((i) => ({ ...i, assignee: null })) }, dicts);
|
||
expect(initialWho(bare, noFilters(), [""]).size).toBe(0);
|
||
});
|
||
});
|