111 lines
4.1 KiB
TypeScript
111 lines
4.1 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
||
import fs from "node:fs";
|
||
import path from "node:path";
|
||
|
||
import { expect, test } from "@playwright/test";
|
||
|
||
const repoRoot = process.cwd();
|
||
const gifFlow = path.join(repoRoot, "apps/web/public/tour/flow-builder.gif");
|
||
const gifRecipe = path.join(repoRoot, "apps/web/public/tour/recipe-sheet.gif");
|
||
|
||
const assertFfmpeg = () => {
|
||
try {
|
||
execFileSync("ffmpeg", ["-version"], { stdio: "ignore" });
|
||
} catch {
|
||
throw new Error("ffmpeg est requis pour npm run tour:capture (ex. apt install ffmpeg)");
|
||
}
|
||
};
|
||
|
||
const webmToGif = (webm: string, gif: string) => {
|
||
execFileSync(
|
||
"ffmpeg",
|
||
[
|
||
"-y",
|
||
"-i",
|
||
webm,
|
||
"-vf",
|
||
"fps=8,scale=360:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128:stats_mode=single[p];[s1][p]paletteuse=dither=bayer",
|
||
gif
|
||
],
|
||
{ stdio: "inherit" }
|
||
);
|
||
};
|
||
|
||
const seedStableSession = async (context: import("@playwright/test").BrowserContext) => {
|
||
await context.addInitScript(() => {
|
||
localStorage.setItem("ben-to-cookie-consent-v1", "analytics-rejected");
|
||
localStorage.setItem("ben-to.welcome-tour-dismissed", "v1");
|
||
});
|
||
};
|
||
|
||
test.describe.configure({ mode: "serial" });
|
||
|
||
test.describe("GIFs public/tour (Playwright + ffmpeg)", () => {
|
||
test("flow-builder.gif", async ({ browser }, testInfo) => {
|
||
assertFfmpeg();
|
||
fs.mkdirSync(path.dirname(gifFlow), { recursive: true });
|
||
const videoDir = testInfo.outputPath("flow-video");
|
||
fs.rmSync(videoDir, { recursive: true, force: true });
|
||
fs.mkdirSync(videoDir, { recursive: true });
|
||
const context = await browser.newContext({
|
||
recordVideo: { dir: videoDir, size: { width: 390, height: 760 } },
|
||
viewport: { width: 390, height: 760 }
|
||
});
|
||
await seedStableSession(context);
|
||
const page = await context.newPage();
|
||
await page.goto("/");
|
||
const firstBase = page.locator(".cards button.card").first();
|
||
await firstBase.waitFor({ state: "visible" });
|
||
await firstBase.click();
|
||
await page.getByRole("button", { name: /Continuer|Continue|계속|继续/i }).click();
|
||
await expect(page.locator(".builder-variant-base-reminder")).toBeVisible({ timeout: 25_000 });
|
||
const firstVariant = page.locator(".cards button.card").first();
|
||
await firstVariant.waitFor({ state: "visible" });
|
||
await firstVariant.click();
|
||
await page.waitForTimeout(500);
|
||
/* S’arrête ici (étape garniture) pour ne pas dupliquer la fiche recette du second GIF. */
|
||
const video = page.video();
|
||
await page.close();
|
||
const webm = await video?.path();
|
||
await context.close();
|
||
if (!webm) throw new Error("Aucun fichier vidéo Playwright");
|
||
webmToGif(webm, gifFlow);
|
||
});
|
||
|
||
test("recipe-sheet.gif", async ({ browser }, testInfo) => {
|
||
assertFfmpeg();
|
||
fs.mkdirSync(path.dirname(gifRecipe), { recursive: true });
|
||
const videoDir = testInfo.outputPath("recipe-video");
|
||
fs.rmSync(videoDir, { recursive: true, force: true });
|
||
fs.mkdirSync(videoDir, { recursive: true });
|
||
const context = await browser.newContext({
|
||
recordVideo: { dir: videoDir, size: { width: 390, height: 760 } },
|
||
viewport: { width: 390, height: 760 }
|
||
});
|
||
await seedStableSession(context);
|
||
const page = await context.newPage();
|
||
await page.goto("/r/base%3Aonigiri/variant%3Aonigiri-kimchi-mozza");
|
||
await expect(page.locator("#recipe-sheet-title")).toBeVisible({ timeout: 25_000 });
|
||
const sheet = page.locator("section.recipe-sheet");
|
||
await page.waitForTimeout(400);
|
||
await sheet.evaluate((el) => {
|
||
el.scrollTo({ top: 0, behavior: "auto" });
|
||
});
|
||
await page.waitForTimeout(450);
|
||
await sheet.evaluate((el) => {
|
||
el.scrollTo({ top: 400, behavior: "auto" });
|
||
});
|
||
await page.waitForTimeout(450);
|
||
await sheet.evaluate((el) => {
|
||
el.scrollTo({ top: 900, behavior: "auto" });
|
||
});
|
||
await page.waitForTimeout(450);
|
||
const video = page.video();
|
||
await page.close();
|
||
const webm = await video?.path();
|
||
await context.close();
|
||
if (!webm) throw new Error("Aucun fichier vidéo Playwright");
|
||
webmToGif(webm, gifRecipe);
|
||
});
|
||
});
|