/**
* `lib/ds-alerts/edit.ts` の期待値表(指示書AX §3 表3。D15)
*
* ★表3 は指示書AX で導き、監督が正としたもの(監督判断 2026-10-19。§11 Q5)。変えないこと★
*
* | # | 入力 | 期待 |
* |----|------|------|
* | S1 | `row`(unresolved・note null)、`updated`(同じ id・resolved・responded_at / resolved_at あり・note「確認済み」) | `row` の4項目だけ差し替え。他は `row` のまま |
* | S2 | `updated.id !== row.id` | 例外 |
* | S3 | summary {2,1,1}、1行が unresolved → resolved | {1,1,2} |
* | S4 | 備考だけ変えた(状態は同じ) | summary は変わらない |
* | S5 | 2行(unresolved → in_progress、in_progress → unresolved) | {2,1,1} のまま |
* | S6 | `updated` が空の Map | 入力と同じ値(入力のオブジェクトを書き換えない) |
*/
import { describe, expect, it } from "vitest";
import { adjustDsAlertSummary, dsAlertWithResolution } from "@/lib/ds-alerts/edit";
import type { DsAlertSummary } from "@/lib/ds-alerts/query";
import type { DsAlert, ErrorReportItem } from "@/lib/types";
function alert(overrides: Partial<DsAlert> & Pick<DsAlert, "id">): DsAlert {
return {
alert_type: "disconnected",
device_serial: "DFAS010001",
facility_id: 3,
facility_name: "テスト施設C",
section_name: "1F売り場",
detected_at: "2026-10-19T01:30:00+09:00",
resolution_status: "unresolved",
responded_at: null,
resolved_at: null,
note: null,
...overrides,
};
}
/** PATCH /errors/{error_id}/status の応答。★DsAlert に無い項目はわざと row と違う値にする★(差し替えないことを見る) */
function updatedItem(overrides: Partial<ErrorReportItem> & Pick<ErrorReportItem, "id">): ErrorReportItem {
return {
detected_at: "2026-10-01T00:00:00+09:00",
facility_id: 99,
facility_name: "別の施設",
serial_number: "OTHER",
error_type: "D-S_CONTROL_FAILURE",
error_level: "CRITICAL",
clean_timetable_id: null,
schedule_link: "none",
precheck_minutes: null,
resolution_status: "unresolved",
responded_at: null,
resolved_at: null,
note: null,
// エラー内容(指示書BD §3-2)。★DsAlert には無い項目★(D-Sec の行は選べない)
error_list_id: null,
error_list: null,
error_list_selectable: false,
...overrides,
};
}
describe("dsAlertWithResolution(表3 S1・S2)", () => {
it("S1: 4項目だけ差し替え、他は row のまま", () => {
const row = alert({ id: "1000004" });
const updated = updatedItem({
id: "1000004",
resolution_status: "resolved",
responded_at: "2026-10-19T09:00:00+09:00",
resolved_at: "2026-10-19T09:30:00+09:00",
note: "確認済み",
});
expect(dsAlertWithResolution(row, updated)).toEqual({
...row,
resolution_status: "resolved",
responded_at: "2026-10-19T09:00:00+09:00",
resolved_at: "2026-10-19T09:30:00+09:00",
note: "確認済み",
});
});
it("S1: 入力の row を書き換えない", () => {
const row = alert({ id: "1" });
const snapshot = { ...row };
dsAlertWithResolution(row, updatedItem({ id: "1", resolution_status: "resolved" }));
expect(row).toEqual(snapshot);
});
it("★S2: id が違えば例外(呼び出しの誤り)★", () => {
expect(() => dsAlertWithResolution(alert({ id: "1" }), updatedItem({ id: "2" }))).toThrow();
});
});
describe("adjustDsAlertSummary(表3 S3〜S6)", () => {
const SUMMARY: DsAlertSummary = { unresolved: 2, in_progress: 1, resolved: 1 };
const BEFORE: DsAlert[] = [
alert({ id: "a", resolution_status: "unresolved" }),
alert({ id: "b", resolution_status: "unresolved" }),
alert({ id: "c", resolution_status: "in_progress" }),
alert({ id: "d", resolution_status: "resolved" }),
];
it("S3: 1行が unresolved → resolved → {1,1,2}", () => {
const updated = new Map([["a", { ...BEFORE[0], resolution_status: "resolved" as const }]]);
expect(adjustDsAlertSummary(SUMMARY, BEFORE, updated)).toEqual({ unresolved: 1, in_progress: 1, resolved: 2 });
});
it("S4: 備考だけ変えた(状態は同じ)→ 変わらない", () => {
const updated = new Map([["b", { ...BEFORE[1], note: "備考だけ" }]]);
expect(adjustDsAlertSummary(SUMMARY, BEFORE, updated)).toEqual(SUMMARY);
});
it("S5: unresolved → in_progress と in_progress → unresolved → {2,1,1} のまま", () => {
const updated = new Map([
["a", { ...BEFORE[0], resolution_status: "in_progress" as const }],
["c", { ...BEFORE[2], resolution_status: "unresolved" as const }],
]);
expect(adjustDsAlertSummary(SUMMARY, BEFORE, updated)).toEqual({ unresolved: 2, in_progress: 1, resolved: 1 });
});
it("★S6: updated が空 → 入力と同じ値・入力のオブジェクトを書き換えない★", () => {
const summary = { ...SUMMARY };
const result = adjustDsAlertSummary(summary, BEFORE, new Map());
expect(result).toEqual(SUMMARY);
expect(summary).toEqual(SUMMARY);
});
it("★入力の summary を書き換えない(状態が変わったとき)★", () => {
const summary = { ...SUMMARY };
adjustDsAlertSummary(summary, BEFORE, new Map([["a", { ...BEFORE[0], resolution_status: "resolved" as const }]]));
expect(summary).toEqual(SUMMARY);
});
});