mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Merge branch 'worktree-agent-ae5b9f86'
This commit is contained in:
@@ -398,3 +398,37 @@ test.describe("Image Enhancement", () => {
|
||||
expect(body.processedSize).not.toBe(body.originalSize);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("adjust-colors without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/adjust-colors", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({ brightness: 20 }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("strip-metadata without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/strip-metadata", {
|
||||
multipart: {
|
||||
file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_WITH_EXIF },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("edit-metadata without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/edit-metadata", {
|
||||
multipart: {
|
||||
file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
|
||||
settings: JSON.stringify({ artist: "Test" }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -754,3 +754,37 @@ test.describe("AI Feature Bundle Status", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("remove-background without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/remove-background", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: TINY_PNG },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("upscale without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/upscale", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: TINY_PNG },
|
||||
settings: JSON.stringify({ scale: 2, model: "auto" }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("ocr without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/ocr", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: TINY_PNG },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { mkdirSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { expect, test as setup } from "@playwright/test";
|
||||
import { test as setup } from "@playwright/test";
|
||||
|
||||
const authFile = path.join(__dirname, "..", "..", ".playwright", ".auth", "analytics-user.json");
|
||||
|
||||
@@ -21,11 +21,18 @@ setup("authenticate", async ({ page }) => {
|
||||
await acceptBtn.waitFor({ state: "visible", timeout: 15_000 });
|
||||
await acceptBtn.click();
|
||||
// Consent page does window.location.href = "/" (full reload)
|
||||
await page.waitForURL("/", { timeout: 30_000 });
|
||||
await page.waitForURL((url) => !url.pathname.includes("analytics-consent"), {
|
||||
timeout: 30_000,
|
||||
});
|
||||
}
|
||||
|
||||
// At this point we should be on the home page
|
||||
await expect(page).toHaveURL("/");
|
||||
// At this point we should be on the home page (or at least past the consent page)
|
||||
await page.waitForURL(
|
||||
(url) => !url.pathname.includes("login") && !url.pathname.includes("analytics-consent"),
|
||||
{
|
||||
timeout: 30_000,
|
||||
},
|
||||
);
|
||||
mkdirSync(path.dirname(authFile), { recursive: true });
|
||||
await page.context().storageState({ path: authFile });
|
||||
});
|
||||
|
||||
@@ -581,3 +581,39 @@ test.describe("Convert format matrix", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("gif-tools without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/gif-tools", {
|
||||
multipart: {
|
||||
file: { name: "animated.gif", mimeType: "image/gif", buffer: ANIMATED_GIF },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("image-to-base64 without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/image-to-base64", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("image-to-pdf without token returns 401", async ({ request }) => {
|
||||
const { body, contentType } = buildMultipart(
|
||||
[{ name: "file", filename: "test.jpg", contentType: "image/jpeg", buffer: JPG_100x100 }],
|
||||
[{ name: "settings", value: JSON.stringify({ pageSize: "A4" }) }],
|
||||
);
|
||||
const res = await request.post("/api/v1/tools/image-to-pdf", {
|
||||
headers: { "Content-Type": contentType },
|
||||
data: body,
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -589,3 +589,57 @@ test.describe("Content-Aware Resize", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("collage without token returns 401", async ({ request }) => {
|
||||
const { body, contentType } = buildMultipart(
|
||||
[
|
||||
{ name: "file", filename: "a.png", contentType: "image/png", buffer: PNG_200x150 },
|
||||
{ name: "file", filename: "b.jpg", contentType: "image/jpeg", buffer: JPG_100x100 },
|
||||
],
|
||||
[
|
||||
{
|
||||
name: "settings",
|
||||
value: JSON.stringify({ templateId: "2-h-equal", width: 400 }),
|
||||
},
|
||||
],
|
||||
);
|
||||
const res = await request.post("/api/v1/tools/collage", {
|
||||
headers: { "Content-Type": contentType },
|
||||
data: body,
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("stitch without token returns 401", async ({ request }) => {
|
||||
const { body, contentType } = buildMultipart(
|
||||
[
|
||||
{ name: "file", filename: "a.png", contentType: "image/png", buffer: PNG_200x150 },
|
||||
{ name: "file", filename: "b.jpg", contentType: "image/jpeg", buffer: JPG_100x100 },
|
||||
],
|
||||
[{ name: "settings", value: JSON.stringify({ direction: "horizontal" }) }],
|
||||
);
|
||||
const res = await request.post("/api/v1/tools/stitch", {
|
||||
headers: { "Content-Type": contentType },
|
||||
data: body,
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("text-overlay without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/text-overlay", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({
|
||||
text: "Test",
|
||||
fontSize: 24,
|
||||
color: "#FFFFFF",
|
||||
position: "center",
|
||||
}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -618,3 +618,37 @@ test.describe("Sharpening", () => {
|
||||
expect(body.downloadUrl).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("resize without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/resize", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({ width: 100 }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("crop without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/crop", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({ left: 0, top: 0, width: 50, height: 50 }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("convert without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/convert", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({ format: "jpg" }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -717,3 +717,37 @@ test.describe("PDF to Image — additional formats", () => {
|
||||
expect(body.downloadUrl || body.pages || body.jobId).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("svg-to-raster without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/svg-to-raster", {
|
||||
multipart: {
|
||||
file: { name: "test.svg", mimeType: "image/svg+xml", buffer: SVG_100x100 },
|
||||
settings: JSON.stringify({ format: "png", width: 200 }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("vectorize without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/vectorize", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("pdf-to-image without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/pdf-to-image", {
|
||||
multipart: {
|
||||
file: { name: "test.pdf", mimeType: "application/pdf", buffer: PDF_3PAGE },
|
||||
settings: JSON.stringify({ format: "png", dpi: 150, pages: "1" }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -543,3 +543,27 @@ test.describe("Border — extended", () => {
|
||||
expect(body.processedSize).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("split without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/split", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({ columns: 2, rows: 2 }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("border without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/border", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({ size: 10, color: "#ff0000" }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -734,3 +734,41 @@ test.describe("Content-Aware Resize — extended", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("optimize-for-web without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/optimize-for-web", {
|
||||
multipart: {
|
||||
file: { name: "test.jpg", mimeType: "image/jpeg", buffer: JPG_100x100 },
|
||||
settings: JSON.stringify({ maxWidth: 800, quality: 75 }),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("favicon without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/favicon", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("replace-color without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/replace-color", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({
|
||||
targetColor: "#ffffff",
|
||||
replacementColor: "#000000",
|
||||
tolerance: 30,
|
||||
}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -758,3 +758,32 @@ test.describe("QR Read", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("info without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/info", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("qr-generate without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/qr-generate", {
|
||||
data: { text: "https://snapotter.app", size: 512 },
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("color-palette without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/color-palette", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -538,3 +538,43 @@ test.describe("Compose — extended", () => {
|
||||
expect(json.downloadUrl).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Auth Failure ──────────────────────────────────────────────────
|
||||
|
||||
test.describe("Auth failure", () => {
|
||||
test("watermark-text without token returns 401", async ({ request }) => {
|
||||
const res = await request.post("/api/v1/tools/watermark-text", {
|
||||
multipart: {
|
||||
file: { name: "test.png", mimeType: "image/png", buffer: PNG_200x150 },
|
||||
settings: JSON.stringify({
|
||||
text: "TEST",
|
||||
fontSize: 24,
|
||||
color: "#ff0000",
|
||||
opacity: 50,
|
||||
position: "center",
|
||||
}),
|
||||
},
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
|
||||
test("compose without token returns 401", async ({ request }) => {
|
||||
const { body, contentType } = buildMultipart(
|
||||
[
|
||||
{ name: "file", filename: "base.png", contentType: "image/png", buffer: PNG_200x150 },
|
||||
{
|
||||
name: "overlay",
|
||||
filename: "overlay.webp",
|
||||
contentType: "image/webp",
|
||||
buffer: WEBP_50x50,
|
||||
},
|
||||
],
|
||||
[{ name: "settings", value: JSON.stringify({ x: 0, y: 0, opacity: 100 }) }],
|
||||
);
|
||||
const res = await request.post("/api/v1/tools/compose", {
|
||||
headers: { "Content-Type": contentType },
|
||||
data: body,
|
||||
});
|
||||
expect(res.status()).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user