Files
paseo/packages/app/src/projects/import-project-icon.test.ts
T
800bd2bef1 feat: add host-local custom project icons (#2335)
* feat(projects): add local icons and colors

* refactor(projects): simplify appearance handling

* fix(projects): serialize appearance saves

* test(app): update project appearance expectations

* test: fix project appearance CI expectations

* refactor(projects): organize appearance code

* fix(server): adopt main's reconcile model in project appearance updates

* fix(projects): preserve host-local appearance targets

* fix(desktop): restore Linux development startup

Ubuntu can block Electron's unprivileged user-namespace fallback while the npm-installed sandbox helper is not SUID. Disable the Chromium process sandbox only in the Linux development runner so packaged desktop policy remains unchanged.

* feat(projects): add custom project icons

Keep URL acquisition in the client so the host daemon only validates uploaded bytes. Project name and icon changes share one adaptive edit sheet.

* refactor(settings): scope projects by host

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-08-01 01:34:42 +08:00

47 lines
1.6 KiB
TypeScript

import { Buffer } from "buffer";
import { describe, expect, it } from "vitest";
import { importProjectIconFromUrl } from "./import-project-icon";
const IMAGE = new Uint8Array([1, 2, 3, 4]);
function response(body: BodyInit, contentType: string): Response {
return new Response(body, { headers: { "content-type": contentType } });
}
describe("project icon URL import", () => {
it("turns a direct image URL into an upload payload", async () => {
const source = await importProjectIconFromUrl("https://example.com/icon.png", async () =>
response(IMAGE.buffer, "image/png"),
);
expect(source).toEqual({ type: "upload", data: Buffer.from(IMAGE).toString("base64") });
});
it("fetches a website icon on the client and returns an upload payload", async () => {
const requested: string[] = [];
const source = await importProjectIconFromUrl("https://example.com", async (input) => {
const url = input.toString();
requested.push(url);
if (url === "https://example.com/") {
return response('<link rel="icon" href="/brand.png">', "text/html");
}
return response(IMAGE.buffer, "image/png");
});
expect(requested).toEqual(["https://example.com/", "https://example.com/brand.png"]);
expect(source.type).toBe("upload");
});
it("rejects non-HTTP URLs without fetching", async () => {
let fetched = false;
await expect(
importProjectIconFromUrl("file:///etc/passwd", async () => {
fetched = true;
return response(IMAGE.buffer, "image/png");
}),
).rejects.toThrow("URL must use HTTP or HTTPS without credentials");
expect(fetched).toBe(false);
});
});