mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
95 lines
3.7 KiB
TypeScript
95 lines
3.7 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { test as base, expect, type Page } from "@playwright/test";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// login() — fill the login form and submit (for tests that need fresh login)
|
|
// ---------------------------------------------------------------------------
|
|
export async function login(page: Page, username = "admin", password = "admin") {
|
|
await page.goto("/login");
|
|
await page.getByLabel("Username").fill(username);
|
|
await page.getByLabel("Password").fill(password);
|
|
await page.getByRole("button", { name: /login/i }).click();
|
|
await page.waitForURL("/", { timeout: 15_000 });
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// createTestImageFile() — create a small test PNG on disk and return its path
|
|
// ---------------------------------------------------------------------------
|
|
let _testImagePath: string | null = null;
|
|
|
|
export function getTestImagePath(): string {
|
|
if (_testImagePath && fs.existsSync(_testImagePath)) return _testImagePath;
|
|
|
|
const dir = path.join(process.cwd(), "test-results");
|
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
|
|
_testImagePath = path.join(dir, "test-image.png");
|
|
|
|
try {
|
|
const script = [
|
|
"const sharp = require('sharp');",
|
|
`sharp({create:{width:100,height:100,channels:4,background:{r:255,g:0,b:0,alpha:1}}}).png().toFile('${_testImagePath.replace(/'/g, "\\'")}')`,
|
|
].join(" ");
|
|
execFileSync("node", ["-e", script], {
|
|
cwd: process.cwd(),
|
|
timeout: 5000,
|
|
});
|
|
} catch {
|
|
// Fallback: write a minimal 1x1 PNG manually
|
|
const minimalPng = Buffer.from(
|
|
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwADhQGAWjR9awAAAABJRU5ErkJggg==",
|
|
"base64",
|
|
);
|
|
fs.writeFileSync(_testImagePath, minimalPng);
|
|
}
|
|
|
|
return _testImagePath;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// uploadTestImage() — upload a test image via the file chooser on a tool page
|
|
// ---------------------------------------------------------------------------
|
|
export async function uploadTestImage(page: Page): Promise<void> {
|
|
const testImagePath = getTestImagePath();
|
|
|
|
const fileChooserPromise = page.waitForEvent("filechooser");
|
|
const dropzone = page.locator("[class*='border-dashed']").first();
|
|
await dropzone.click();
|
|
const fileChooser = await fileChooserPromise;
|
|
await fileChooser.setFiles(testImagePath);
|
|
|
|
// Wait for React state to update
|
|
await page.waitForTimeout(500);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// waitForProcessing() — wait for processing to complete
|
|
// ---------------------------------------------------------------------------
|
|
export async function waitForProcessing(page: Page, timeoutMs = 30_000) {
|
|
try {
|
|
const spinner = page.locator("[class*='animate-spin']");
|
|
if (await spinner.isVisible({ timeout: 2000 })) {
|
|
await spinner.waitFor({ state: "hidden", timeout: timeoutMs });
|
|
}
|
|
} catch {
|
|
// No spinner appeared — processing may have been instant
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Custom test fixture — loggedInPage uses the saved storageState
|
|
// (all "chromium" project tests already have auth via storageState,
|
|
// but this provides backward compatibility for tests that use it)
|
|
// ---------------------------------------------------------------------------
|
|
export const test = base.extend<{ loggedInPage: Page }>({
|
|
loggedInPage: async ({ page }, use) => {
|
|
// storageState is already loaded by the project config, just navigate
|
|
await page.goto("/");
|
|
await use(page);
|
|
},
|
|
});
|
|
|
|
export { expect };
|