Files
next-ai-draw-io/tests/e2e/file-upload.spec.ts
T
dayuan.jiang 1333ed68c6 test: shared e2e helpers, vi.stubEnv, drop placeholder specs
- tests/e2e/lib: openApp(page, { path, config }), MODEL_CONFIGS_KEY,
  savedModelConfigs, settingsDialog, chunkedReplies, sse() and
  toolCallEvents() replace about 70 copies of goto + wait for iframe,
  three local openApp functions, 14 window.fetch overrides and the
  Node-side SSE serialisers; unused fixtures removed
- delete theme, save, history, model-config, upload and copy-paste
  specs (the copy-button test moves to chat.spec.ts); trim
  iframe-interaction, history-restore, keyboard and smoke to tests that
  can fail; file-upload asserts on the preview image
- settings-review-fixes.spec.ts split by topic into settings-bedrock,
  settings-tabs-sync and settings-providers
- unit tests use vi.stubEnv with unstubEnvs: true instead of
  hand-written process.env save and restore loops
2026-10-12 09:11:25 +09:00

123 lines
3.8 KiB
TypeScript

import { SINGLE_BOX_XML } from "./fixtures/diagrams"
import {
expect,
getAttachmentInput,
openApp,
sendMessage,
test,
} from "./lib/fixtures"
import { createMockSSEResponse } from "./lib/helpers"
const ONE_PIXEL_PNG = Buffer.from(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"base64",
)
test.describe("File Upload", () => {
test("upload button opens file picker", async ({ page }) => {
await openApp(page)
// The "Add" menu holds the upload entry
const addButton = page.locator('[data-testid="composer-add"]')
await expect(addButton).toBeVisible({ timeout: 10000 })
await addButton.click()
const [chooser] = await Promise.all([
page.waitForEvent("filechooser"),
page.getByRole("button", { name: "Upload file" }).click(),
])
expect(chooser.isMultiple()).toBe(true)
})
test("can remove uploaded file", async ({ page }) => {
await openApp(page)
await getAttachmentInput(page).setInputFiles({
name: "test-image.png",
mimeType: "image/png",
buffer: ONE_PIXEL_PNG,
})
// The image shows as a preview
await expect(page.getByAltText("test-image.png")).toBeVisible({
timeout: 3000,
})
const removeButton = page.getByRole("button", { name: "Remove file" })
await removeButton.first().click()
await expect(removeButton).toHaveCount(0, { timeout: 2000 })
await expect(page.getByAltText("test-image.png")).toHaveCount(0)
})
test("sends file with message to API", async ({ page }) => {
let capturedRequest: any = null
await page.route("**/api/chat", async (route) => {
capturedRequest = route.request()
await route.fulfill({
status: 200,
contentType: "text/event-stream",
body: createMockSSEResponse(
SINGLE_BOX_XML,
"Based on your image, here is a diagram:",
),
})
})
await openApp(page)
await getAttachmentInput(page).setInputFiles({
name: "architecture.png",
mimeType: "image/png",
buffer: ONE_PIXEL_PNG,
})
await sendMessage(page, "Convert this to a diagram")
await expect(
page.locator('text="Based on your image, here is a diagram:"'),
).toBeVisible({ timeout: 15000 })
expect(capturedRequest).not.toBeNull()
})
test("shows error for oversized file", async ({ page }) => {
await openApp(page)
const fileInput = getAttachmentInput(page)
const largeBuffer = Buffer.alloc(3 * 1024 * 1024, "x")
await fileInput.setInputFiles({
name: "large-image.png",
mimeType: "image/png",
buffer: largeBuffer,
})
await expect(
page.locator('[role="alert"], [data-sonner-toast]').first(),
).toBeVisible({ timeout: 5000 })
})
test("drag and drop file upload works", async ({ page }) => {
await openApp(page)
const chatForm = page.locator("form").first()
const dataTransfer = await page.evaluateHandle(() => {
const dt = new DataTransfer()
const file = new File(["test content"], "dropped-image.png", {
type: "image/png",
})
dt.items.add(file)
return dt
})
await chatForm.dispatchEvent("dragover", { dataTransfer })
await chatForm.dispatchEvent("drop", { dataTransfer })
// The dropped file shows as a preview
await expect(page.getByAltText("dropped-image.png")).toBeVisible({
timeout: 3000,
})
})
})