first commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user