import { describe, expect, it } from "vitest"; import type { RevolutionSign } from "../../model/slotTypes"; import { groupPasses } from "./slotPasses"; /** Минимальный слот для группировки в витки. */ type S = { satelliteId: number; slotNumber: number; cycle: number; revolution: number; revolutionSign: RevolutionSign; tn: string; }; const keyOf = (s: S) => `${s.satelliteId}:${s.slotNumber}:${s.cycle}`; /** Слот на минуту mm от базовой даты; виток задаётся (revolution, sign, cycle). */ function slot( satelliteId: number, slotNumber: number, mm: number, revolution: number, revolutionSign: RevolutionSign = "ASC", cycle = 1, ): S { return { satelliteId, slotNumber, cycle, revolution, revolutionSign, tn: `2026-06-17T10:${String(mm).padStart(2, "0")}:00`, }; } describe("groupPasses", () => { it("пустой вход → пустой список", () => { expect(groupPasses([], keyOf)).toEqual([]); }); it("веер кренов одного оборота → один виток (крен не дробит)", () => { // Три нацеливания одного прохода КА 1, оборот 100, восх — все в один виток. const passes = groupPasses( [slot(1, 1, 0, 100), slot(1, 2, 0, 100), slot(1, 3, 1, 100)], keyOf, ); expect(passes).toHaveLength(1); expect(passes[0].id).toBe("1:1:100:ASC"); expect(passes[0].keys).toEqual(["1:1:1", "1:2:1", "1:3:1"]); expect(passes[0].satelliteId).toBe(1); expect(passes[0].revolution).toBe(100); }); it("разные обороты / ветви / КА → разные витки", () => { const passes = groupPasses( [ slot(1, 1, 0, 100, "ASC"), slot(1, 2, 5, 100, "DESC"), // та же revolution, другая ветвь slot(1, 3, 10, 101, "ASC"), // другой оборот slot(2, 4, 2, 100, "ASC"), // другой КА ], keyOf, ); expect(passes.map((p) => p.id)).toEqual([ "1:1:100:ASC", // 10:00 "2:1:100:ASC", // 10:02 "1:1:100:DESC", // 10:05 "1:1:101:ASC", // 10:10 ]); }); it("витки упорядочены по началу прохода (хронология по всем КА)", () => { const passes = groupPasses( [slot(1, 1, 30, 100), slot(2, 2, 5, 200), slot(1, 3, 15, 101)], keyOf, ); expect(passes.map((p) => p.startMs)).toEqual( [...passes.map((p) => p.startMs)].sort((a, b) => a - b), ); expect(passes[0].satelliteId).toBe(2); // самый ранний (10:05) }); it("ключи внутри витка отсортированы по времени", () => { const passes = groupPasses( [slot(1, 3, 2, 100), slot(1, 1, 0, 100), slot(1, 2, 1, 100)], keyOf, ); expect(passes[0].keys).toEqual(["1:1:1", "1:2:1", "1:3:1"]); }); });