1import { beforeEach, describe, expect, it } from "vitest"
2
3import {
4 serializeSession,
5 validateRecord,
6 type SessionState,
7} from "@/features/session/sessionDb"
8import { useBoothStore, type Shot } from "@/stores/booth"
9
10/* M8 (SE-04, SE-05, SE-10): irisan estafet di store dan rekaman sesi. Yang
11 dijaga: sesi estafet dibersihkan bersama sesi lain, dan bentuk rekamannya
12 menerima catatan lama yang belum punya bidang `relay`. */
13
14const SHOT: Shot = { still: "data:image/jpeg;base64,AAAA", capturedAt: 1 }
15
16const RELAY = {
17 id: "relayid12345",
18 role: "guest" as const,
19 lockedSlots: [0, 2],
20 ghostEnabled: true,
21}
22
23function state(overrides: Partial<SessionState> = {}): SessionState {
24 return {
25 layoutId: "strip-4",
26 shots: [SHOT, null, null, null],
27 frameId: "klasik",
28 effectId: "asli",
29 stickers: [],
30 texts: [],
31 showDate: false,
32 share: { qrEnabled: false, strip: null },
33 relay: null,
34 localOnly: false,
35 ...overrides,
36 }
37}
38
39describe("irisan estafet di store", () => {
40 beforeEach(() => {
41 useBoothStore.getState().reset()
42 })
43
44 it("menyimpan peran, slot terkunci, dan sakelar bayangan", () => {
45 const store = useBoothStore.getState()
46 store.setLayout("strip-4")
47 store.setRelay(RELAY)
48 expect(useBoothStore.getState().relay).toEqual(RELAY)
49
50 store.setGhostEnabled(false)
51 expect(useBoothStore.getState().relay?.ghostEnabled).toBe(false)
52 /* Tanpa sesi estafet tidak ada yang diubah. */
53 store.setRelay(null)
54 store.setGhostEnabled(true)
55 expect(useBoothStore.getState().relay).toBeNull()
56 })
57
58 it("ganti layout dan mulai dari awal membuang sesi estafetnya", () => {
59 const store = useBoothStore.getState()
60 store.setLayout("strip-4")
61 store.setRelay(RELAY)
62 store.setLayout("strip-3")
63 expect(useBoothStore.getState().relay).toBeNull()
64
65 store.setRelay(RELAY)
66 store.setLocalOnly(true)
67 store.reset()
68 expect(useBoothStore.getState().relay).toBeNull()
69 expect(useBoothStore.getState().localOnly).toBe(false)
70 })
71})
72
73describe("rekaman sesi estafet", () => {
74 it("serialisasi menyertakan relay dan menerima absennya", () => {
75 expect(serializeSession(state({ relay: RELAY })).relay).toEqual(RELAY)
76 /* Pemanggil lama tidak mengisi bidang ini; hasilnya null, bukan undefined,
77 supaya bentuk rekaman selalu sama. */
78 expect(serializeSession(state()).relay).toBeNull()
79 /* SE-10: salinan lokal tetap lokal setelah halaman dimuat ulang. */
80 const local = serializeSession(state({ localOnly: true }))
81 expect(local.localOnly).toBe(true)
82 expect(validateRecord(local)?.localOnly).toBe(true)
83 expect(validateRecord({ ...local, localOnly: undefined })?.localOnly).toBe(false)
84 })
85
86 it("menerima rekaman lama tanpa bidang relay", () => {
87 const record: Record<string, unknown> = {
88 ...serializeSession(state()),
89 relay: RELAY,
90 }
91 delete record.relay
92 expect(validateRecord(record)?.relay).toBeNull()
93 })
94
95 it("menolak relay yang rusak dan menerima yang benar", () => {
96 const record = serializeSession(state({ relay: RELAY }))
97 expect(validateRecord(record)?.relay).toEqual(RELAY)
98
99 expect(validateRecord({ ...record, relay: { ...RELAY, role: "wasit" } })).toBeNull()
100 expect(validateRecord({ ...record, relay: { ...RELAY, lockedSlots: [0, "2"] } })).toBeNull()
101 expect(validateRecord({ ...record, relay: { ...RELAY, ghostEnabled: "nyala" } })).toBeNull()
102 expect(validateRecord({ ...record, relay: { ...RELAY, id: "pendek" } })).toBeNull()
103 })
104})
105