IKHSAN
EN Read in EnglishID

snapme

Publik
Branch
master
Commit terakhir
130fdb828 Oktober 2026

live.spec.ts

Buka raw
import { statSync } from "node:fs"
import path from "node:path"
import { expect, test } from "@playwright/test"

import {
  canvasChecksum,
  masukHias,
  masukHasil,
  matikanGesture,
} from "./helpers"

/* M7 (SH-01 sampai SH-03): Strip Hidup. Uji ini memakai kamera palsu Chromium,
   jadi klip benar-benar terekam selama hitung mundur. Semuanya berjalan lokal
   di peramban: tidak ada lagi klip yang diunggah ke server. */
const FIXTURE_DIR = path.join(process.cwd(), "tests", "e2e", "fixtures")

test.beforeEach(async ({ page }) => {
  await matikanGesture(page)
})

test("sakelar Strip Hidup memutar klip di kanvas", async ({ page }) => {
  await masukHias(page)
  const sakelar = page.getByRole("switch", { name: "Strip Hidup" })
  await expect(sakelar).toBeEnabled()
  await expect(sakelar).not.toBeChecked()

  /* Sebelum dinyalakan kanvas diam. */
  const diamSatu = await canvasChecksum(page)
  await page.waitForTimeout(500)
  expect(await canvasChecksum(page)).toBe(diamSatu)

  await sakelar.click()
  await expect(sakelar).toBeChecked()
  await expect(page.getByText("Nyala", { exact: true })).toBeVisible()
  await expect(
    page.getByText("Versi hidup ikut diunggah saat kamu membuat link.")
  ).toBeVisible()

  /* SH-02: pratinjau benar-benar berputar, bukan hanya lencananya muncul.
     Penggambaran ulang kanvas tidak sinkron dengan klik, jadi hasilnya
     ditunggu, bukan dibandingkan tepat setelah sakelar dinyalakan (M9). */
  await expect.poll(() => canvasChecksum(page)).not.toBe(diamSatu)

  await sakelar.click()
  await expect(sakelar).not.toBeChecked()
  /* Kembali ke foto tetap: nilainya sama dengan sebelum dinyalakan. */
  await expect.poll(() => canvasChecksum(page)).toBe(diamSatu)
  const matiSatu = await canvasChecksum(page)
  await page.waitForTimeout(500)
  expect(await canvasChecksum(page)).toBe(matiSatu)
})

test("prefers-reduced-motion: pratinjau berhenti dengan tombol Putar", async ({
  page,
}) => {
  await page.emulateMedia({ reducedMotion: "reduce" })
  await masukHias(page)

  const tanpaHidup = await canvasChecksum(page)
  await page.getByRole("switch", { name: "Strip Hidup" }).click()

  /* Berhenti: bingkai klip tidak berjalan, tetapi lencana "Klip" membuktikan
     bingkainya memang terekam (tampilannya berbeda dari saat sakelar mati).
     Penggambaran ulangnya ditunggu karena tidak sinkron dengan klik (M9). */
  await expect.poll(() => canvasChecksum(page)).not.toBe(tanpaHidup)
  const berhentiSatu = await canvasChecksum(page)
  await page.waitForTimeout(500)
  expect(await canvasChecksum(page)).toBe(berhentiSatu)

  const putar = page.getByRole("button", { name: "Putar" })
  await expect(putar).toBeVisible()
  await putar.click()
  await expect(page.getByRole("button", { name: "Jeda" })).toBeVisible()

  const jalanSatu = await canvasChecksum(page)
  await expect.poll(() => canvasChecksum(page)).not.toBe(jalanSatu)
  await page.waitForTimeout(500)
  expect(await canvasChecksum(page)).not.toBe(jalanSatu)

  await page.getByRole("button", { name: "Jeda" }).click()
  /* Berhenti lagi pada bingkai pertama, jadi tampilannya kembali ke keadaan
     sebelum diputar. */
  await expect.poll(() => canvasChecksum(page)).toBe(berhentiSatu)
  const jedaSatu = await canvasChecksum(page)
  await page.waitForTimeout(500)
  expect(await canvasChecksum(page)).toBe(jedaSatu)
})

test("tanpa klip: sakelar nonaktif dengan penjelasannya", async ({ page }) => {
  /* Foto dari galeri tidak punya klip, jadi Strip Hidup tidak punya bahan. */
  await page.goto("/")
  const chooser = page.waitForEvent("filechooser")
  await page.getByRole("button", { name: "Pakai Foto Galeri" }).click()
  await (await chooser).setFiles([
    path.join(FIXTURE_DIR, "foto-1.png"),
    path.join(FIXTURE_DIR, "foto-2.png"),
    path.join(FIXTURE_DIR, "foto-3.png"),
    path.join(FIXTURE_DIR, "foto-4.png"),
  ])
  await page.waitForURL("**/booth/customize")
  await expect(page.locator("canvas")).toBeVisible()

  const sakelar = page.getByRole("switch", { name: "Strip Hidup" })
  await expect(sakelar).toBeDisabled()
  await expect(sakelar).not.toBeChecked()
  await expect(
    page.getByText("Klip hanya terekam saat memotret lewat kamera.")
  ).toBeVisible()
})

test("unduh video versi hidup di langkah Hasil", async ({ page }) => {
  /* Rekaman dua putaran butuh sekitar 3 detik; batas bawaannya cukup, tetapi
     headless menambah waktu penyandian, jadi diberi ruang. */
  test.setTimeout(120_000)
  await masukHasil(page)

  const unduh = page.getByRole("button", { name: "Unduh Video" })
  await expect(unduh).toBeVisible()
  const [download] = await Promise.all([
    page.waitForEvent("download"),
    unduh.click(),
  ])

  await expect(
    page.getByText("Video strip tersimpan di perangkatmu.")
  ).toBeVisible()
  expect(download.suggestedFilename()).toMatch(/^snapme-\d{8}-\d{4}\.(webm|mp4)$/)

  /* SH-03: durasi sekitar 3 detik, berkasnya di bawah 5 MB. */
  const berkas = await download.path()
  if (berkas === null) {
    throw new Error("Berkas unduhan tidak tersedia di disk")
  }
  const ukuran = statSync(berkas).size
  expect(ukuran).toBeGreaterThan(0)
  expect(ukuran).toBeLessThan(5_242_880)
})
byte
5.179
baris
138
Jenis
ts
Commit terakhir
28 Oktober 2026