feat: use export testing

This commit is contained in:
Marc Diaz
2026-04-07 12:58:33 -04:00
parent 24928164ca
commit 6bff2a2a2c
7 changed files with 1857 additions and 197 deletions
+13
View File
@@ -31,6 +31,19 @@ jobs:
- run: npm ci
- run: npx tsc --noEmit
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npm run test:browser
build:
name: Build
runs-on: ubuntu-latest
+4 -1
View File
@@ -29,4 +29,7 @@ release/**
# Playwright
test-results
playwright-report/
playwright-report/
# Vitest browser mode screenshots
__screenshots__/
+1721 -196
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -26,6 +26,7 @@
"test": "vitest --run",
"test:watch": "vitest",
"build-vite": "tsc && vite build",
"test:browser": "vitest --config vitest.browser.config.ts --run",
"test:e2e": "playwright test",
"prepare": "husky"
},
@@ -82,6 +83,8 @@
"@types/react-dom": "^18.2.21",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/browser": "^4.0.16",
"@vitest/browser-playwright": "^4.0.16",
"autoprefixer": "^10.4.21",
"electron": "^39.2.7",
"electron-builder": "^26.7.0",
@@ -0,0 +1,43 @@
import { describe, expect, it } from "vitest";
import sampleVideoUrl from "../../../tests/fixtures/sample.webm?url";
import { GifExporter } from "./gifExporter";
import type { ExportProgress } from "./types";
describe("GifExporter (real browser)", () => {
it("exports a valid GIF blob from a real video", async () => {
const progressEvents: ExportProgress[] = [];
const exporter = new GifExporter({
videoUrl: sampleVideoUrl,
width: 320,
height: 180,
frameRate: 15,
loop: true,
sizePreset: "medium",
wallpaper: "#1a1a2e",
zoomRegions: [],
showShadow: false,
shadowIntensity: 0,
showBlur: false,
cropRegion: { x: 0, y: 0, width: 1, height: 1 },
onProgress: (p) => progressEvents.push(p),
});
const result = await exporter.export();
expect(result.success, result.error).toBe(true);
expect(result.blob).toBeInstanceOf(Blob);
const buf = await result.blob!.arrayBuffer();
const header = new TextDecoder().decode(new Uint8Array(buf, 0, 6));
expect(header).toMatch(/^GIF8[79]a/);
expect(result.blob!.size).toBeGreaterThan(1024);
expect(progressEvents.length).toBeGreaterThan(0);
const finalizing = progressEvents.filter((p) => p.phase === "finalizing");
expect(finalizing.length).toBeGreaterThan(0);
expect(finalizing.at(-1)!.percentage).toBe(100);
});
});
@@ -0,0 +1,43 @@
import { describe, expect, it } from "vitest";
import sampleVideoUrl from "../../../tests/fixtures/sample.webm?url";
import type { ExportProgress } from "./types";
import { VideoExporter } from "./videoExporter";
describe("VideoExporter (real browser)", () => {
it("exports a valid MP4 blob from a real video", async () => {
const progressEvents: ExportProgress[] = [];
const exporter = new VideoExporter({
videoUrl: sampleVideoUrl,
width: 320,
height: 180,
frameRate: 15,
bitrate: 1_000_000,
wallpaper: "#1a1a2e",
zoomRegions: [],
showShadow: false,
shadowIntensity: 0,
showBlur: false,
cropRegion: { x: 0, y: 0, width: 1, height: 1 },
onProgress: (p) => progressEvents.push(p),
});
const result = await exporter.export();
expect(result.success, result.error).toBe(true);
expect(result.blob).toBeInstanceOf(Blob);
const buf = await result.blob!.arrayBuffer();
const bytes = new Uint8Array(buf);
const ftyp = new TextDecoder().decode(bytes.slice(4, 8));
expect(ftyp).toBe("ftyp");
expect(result.blob!.size).toBeGreaterThan(1024);
expect(progressEvents.length).toBeGreaterThan(0);
const finalizing = progressEvents.filter((p) => p.phase === "finalizing");
expect(finalizing.length).toBeGreaterThan(0);
expect(finalizing.at(-1)!.percentage).toBe(100);
});
});
+30
View File
@@ -0,0 +1,30 @@
import path from "node:path";
import { playwright } from "@vitest/browser-playwright";
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
include: ["src/**/*.browser.test.{ts,tsx}"],
browser: {
enabled: true,
provider: playwright({
launch: {
// Software WebGL so Pixi.js works in headless CI without a GPU.
args: ["--enable-unsafe-swiftshader", "--use-gl=swiftshader"],
},
}),
headless: true,
instances: [{ browser: "chromium" }],
},
// GIF export encodes frames and renders — give it plenty of time.
testTimeout: 120_000,
hookTimeout: 30_000,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
// Let Vite treat .webm and .wasm files as static assets importable via `?url`.
assetsInclude: ["**/*.webm"],
});