mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 05:18:36 +00:00
Add end-to-end HTTP tests under backend/test/e2e/ using Node.js built-in test runner (node:test) and native fetch. Tests run through the devenv nginx proxy on port 3450. Test suites (19 tests total): - auth-flow: demo profile creation, login, session cookies, access tokens - export-binfile: file creation, export to asset URL via SSE - asset-download: download with cookie/token auth, 401 without auth, S3 redirect behavior, full export-to-download flow Key findings documented in tests: - nginx @handle_redirect intercepts backend 307 and proxies to S3 directly, stripping the client Authorization header (bug does not reproduce in devenv) - SSE end event uses ~#uri tagged format for URLs - Unauthenticated RPC returns uuid/zero profile (not null) AI-assisted-by: mimo-v2.5-pro Signed-off-by: Andrey Antukh <niwi@niwi.nz>
88 lines
2.5 KiB
JavaScript
88 lines
2.5 KiB
JavaScript
import { describe, it, before } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { setupTestProfile } from "./helpers/auth.mjs";
|
|
import { rpcPost } from "./helpers/client.mjs";
|
|
import { parseSSE, extractResult } from "./helpers/sse.mjs";
|
|
|
|
async function createFile(cookie, projectId, name = "E2E Test File") {
|
|
const res = await rpcPost(
|
|
"create-file",
|
|
{ name, projectId },
|
|
{ cookieToken: cookie }
|
|
);
|
|
assert.equal(res.status, 200, `create-file failed: ${JSON.stringify(res.body)}`);
|
|
return res.body;
|
|
}
|
|
|
|
async function exportFile(cookie, fileId) {
|
|
const res = await rpcPost(
|
|
"export-binfile",
|
|
{
|
|
fileId,
|
|
includeLibraries: false,
|
|
embedAssets: true,
|
|
},
|
|
{ cookieToken: cookie }
|
|
);
|
|
assert.equal(res.status, 200, `export-binfile failed: ${JSON.stringify(res.body)}`);
|
|
|
|
const events = parseSSE(res.body);
|
|
const assetUrl = extractResult(events);
|
|
return assetUrl;
|
|
}
|
|
|
|
describe("export-binfile", () => {
|
|
let profile, cookie;
|
|
|
|
before(async () => {
|
|
const setup = await setupTestProfile();
|
|
profile = setup.profile;
|
|
cookie = setup.cookie;
|
|
});
|
|
|
|
it("creates a file via API", async () => {
|
|
const file = await createFile(cookie, profile.defaultProjectId);
|
|
assert.ok(file.id, "file should have an id");
|
|
assert.equal(file.name, "E2E Test File");
|
|
});
|
|
|
|
it("export returns an asset URL", async () => {
|
|
const file = await createFile(cookie, profile.defaultProjectId);
|
|
const assetUrl = await exportFile(cookie, file.id);
|
|
assert.ok(
|
|
typeof assetUrl === "string" && assetUrl.includes("/assets/by-id/"),
|
|
`asset URL should contain /assets/by-id/, got: ${assetUrl}`
|
|
);
|
|
assert.match(assetUrl, /\/assets\/by-id\/[0-9a-f-]+$/);
|
|
});
|
|
|
|
it("export with invalid file-id returns error", async () => {
|
|
const fakeId = "00000000-0000-0000-0000-000000000000";
|
|
const res = await rpcPost(
|
|
"export-binfile",
|
|
{
|
|
fileId: fakeId,
|
|
includeLibraries: false,
|
|
embedAssets: true,
|
|
},
|
|
{ cookieToken: cookie }
|
|
);
|
|
assert.ok(
|
|
res.body.type || res.status !== 200,
|
|
"should return error for non-existent file"
|
|
);
|
|
});
|
|
|
|
it("export requires authentication", async () => {
|
|
const res = await rpcPost("export-binfile", {
|
|
fileId: "00000000-0000-0000-0000-000000000000",
|
|
includeLibraries: false,
|
|
embedAssets: true,
|
|
});
|
|
assert.ok(
|
|
res.body.type || res.status !== 200,
|
|
"should require authentication"
|
|
);
|
|
});
|
|
});
|