import { test, expect } from "@playwright/test";
// 1x1 red JPEG as base64
const TINY_JPEG_B64 =
"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkS" +
"Ew8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJ" +
"CQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy" +
"MjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACf/" +
"EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AKwA//9k=";
test.describe("Blossom image rendering", () => {
test("Chrome renders
with application/octet-stream", async ({ page }) => {
await page.route("**/mock-blossom/**", async (route) => {
const jpegBytes = Buffer.from(TINY_JPEG_B64, "base64");
await route.fulfill({
status: 200,
contentType: "application/octet-stream",
body: jpegBytes,
});
});
await page.goto("/");
await page.waitForLoadState("domcontentloaded");
const result = await page.evaluate(async () => {
const img = document.createElement("img");
img.src = "/mock-blossom/test.jpg";
document.body.prepend(img);
await new Promise((resolve) => {
img.onload = () => resolve();
img.onerror = () => resolve();
setTimeout(resolve, 3000);
});
return {
naturalWidth: img.naturalWidth,
naturalHeight: img.naturalHeight,
};
});
console.log("Direct
with octet-stream:", result);
expect(result.naturalWidth, "Image should render despite octet-stream content-type").toBeGreaterThan(0);
});
test("ChatMessage component renders imeta images", async ({ page }) => {
// Mock blossom-like endpoint
await page.route("**/mock-blossom/**", async (route) => {
const jpegBytes = Buffer.from(TINY_JPEG_B64, "base64");
await route.fulfill({
status: 200,
contentType: "application/octet-stream",
body: jpegBytes,
});
});
await page.goto("/");
await page.waitForLoadState("domcontentloaded");
// Inject a ChatMessage-like rendering with imeta tags
const result = await page.evaluate(async () => {
const container = document.createElement("div");
container.id = "test-chat";
document.body.prepend(container);
// Simulate the imeta extraction logic from ChatMessage.svelte
const tags = [
["imeta", "url /mock-blossom/chat-image", "m image/jpeg", "x abc123"],
];
const imetaImages = tags
.filter((t) => t[0] === "imeta" && t.some((v) => v.startsWith("m image/")))
.map((t) => ({
url: t.find((v) => v.startsWith("url "))?.slice(4) || "",
mime: t.find((v) => v.startsWith("m "))?.slice(2) || "image/jpeg",
}))
.filter((m) => m.url);
// Render like the template does
for (const img of imetaImages) {
const a = document.createElement("a");
a.href = img.url;
a.target = "_blank";
const imgEl = document.createElement("img");
imgEl.src = img.url;
imgEl.alt = "";
imgEl.style.maxWidth = "100%";
imgEl.style.borderRadius = "8px";
a.appendChild(imgEl);
container.appendChild(a);
}
// Wait for images to load
await new Promise((r) => setTimeout(r, 2000));
const imgs = container.querySelectorAll("img");
const results: any[] = [];
for (const img of imgs) {
results.push({
naturalWidth: (img as HTMLImageElement).naturalWidth,
naturalHeight: (img as HTMLImageElement).naturalHeight,
src: (img as HTMLImageElement).src.substring(0, 60),
});
}
return { imageCount: imetaImages.length, rendered: results };
});
console.log("ChatMessage rendering:", JSON.stringify(result, null, 2));
expect(result.imageCount).toBe(1);
expect(result.rendered[0].naturalWidth).toBeGreaterThan(0);
});
test("imeta URL is suppressed from link rendering", async ({ page }) => {
await page.goto("/");
await page.waitForLoadState("domcontentloaded");
// Simulate the duplicate-suppression logic
const result = await page.evaluate(() => {
const tags = [
["imeta", "url https://blossom.example.com/abc123", "m image/jpeg"],
];
const content = "https://blossom.example.com/abc123";
// Extract imeta URLs
const imetaImages = tags
.filter((t) => t[0] === "imeta" && t.some((v) => v.startsWith("m image/")))
.map((t) => ({
url: t.find((v) => v.startsWith("url "))?.slice(4) || "",
}))
.filter((m) => m.url);
const imetaUrls = new Set(imetaImages.map((i) => i.url));
// Check if the content URL would be suppressed
return {
contentUrl: content,
imetaUrls: [...imetaUrls],
wouldSuppress: imetaUrls.has("https://blossom.example.com/abc123"),
};
});
console.log("Duplicate suppression:", result);
expect(result.wouldSuppress).toBe(true);
});
});