mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-04 16:57:48 +08:00
- Template dialogs no longer submit the outer chat form - Sending is blocked while files or URLs are still extracting - File and URL extraction no longer drop or resurrect entries - IME composition Enter no longer sends - Tool call cards show the error text; keyboard handling on cards fixed - Template import available when empty, edit dialog resets, saved templates refresh - Only png/jpeg/gif/webp images accepted, SVG sent as text; PDF objects released - parse-url request sends the access code
103 lines
3.5 KiB
TypeScript
103 lines
3.5 KiB
TypeScript
import { act, renderHook } from "@testing-library/react"
|
|
import { beforeEach, describe, expect, it, vi } from "vitest"
|
|
import { extractPdfText, extractTextFileContent } from "@/lib/pdf-utils"
|
|
import { useFileProcessor } from "@/lib/use-file-processor"
|
|
|
|
vi.mock("sonner", () => ({ toast: { error: vi.fn() } }))
|
|
vi.mock("@/lib/pdf-utils", async (importOriginal) => ({
|
|
...(await importOriginal<typeof import("@/lib/pdf-utils")>()),
|
|
extractPdfText: vi.fn(),
|
|
extractTextFileContent: vi.fn(),
|
|
}))
|
|
|
|
// A promise we can resolve from the test, to control extraction timing
|
|
function deferred<T>() {
|
|
let resolve!: (value: T) => void
|
|
const promise = new Promise<T>((r) => {
|
|
resolve = r
|
|
})
|
|
return { promise, resolve }
|
|
}
|
|
|
|
const pdfFile = () =>
|
|
new File(["%PDF"], "slow.pdf", { type: "application/pdf" })
|
|
const textFile = () => new File(["notes"], "notes.txt", { type: "text/plain" })
|
|
|
|
describe("useFileProcessor", () => {
|
|
beforeEach(() => {
|
|
vi.mocked(extractPdfText).mockReset()
|
|
vi.mocked(extractTextFileContent).mockReset()
|
|
})
|
|
|
|
it("marks queued files as extracting before the first one finishes", async () => {
|
|
const pdf = deferred<string>()
|
|
vi.mocked(extractPdfText).mockReturnValue(pdf.promise)
|
|
vi.mocked(extractTextFileContent).mockResolvedValue("notes")
|
|
const a = pdfFile()
|
|
const b = textFile()
|
|
const { result } = renderHook(() => useFileProcessor())
|
|
|
|
let done!: Promise<void>
|
|
act(() => {
|
|
done = result.current.handleFileChange([a, b])
|
|
})
|
|
|
|
expect(result.current.pdfData.get(a)?.isExtracting).toBe(true)
|
|
expect(result.current.pdfData.get(b)?.isExtracting).toBe(true)
|
|
|
|
await act(async () => {
|
|
pdf.resolve("pdf text")
|
|
await done
|
|
})
|
|
expect(result.current.pdfData.get(a)?.text).toBe("pdf text")
|
|
expect(result.current.pdfData.get(b)?.text).toBe("notes")
|
|
})
|
|
|
|
it("keeps text of a file added while an earlier file is extracting", async () => {
|
|
const pdf = deferred<string>()
|
|
vi.mocked(extractPdfText).mockReturnValue(pdf.promise)
|
|
vi.mocked(extractTextFileContent).mockResolvedValue("notes")
|
|
const a = pdfFile()
|
|
const b = textFile()
|
|
const { result } = renderHook(() => useFileProcessor())
|
|
|
|
let first!: Promise<void>
|
|
act(() => {
|
|
first = result.current.handleFileChange([a])
|
|
})
|
|
await act(async () => {
|
|
await result.current.handleFileChange([a, b])
|
|
})
|
|
expect(result.current.pdfData.get(b)?.text).toBe("notes")
|
|
|
|
await act(async () => {
|
|
pdf.resolve("pdf text")
|
|
await first
|
|
})
|
|
expect(result.current.pdfData.get(a)?.text).toBe("pdf text")
|
|
expect(result.current.pdfData.get(b)?.text).toBe("notes")
|
|
})
|
|
|
|
it("does not bring back a file removed while extracting", async () => {
|
|
const pdf = deferred<string>()
|
|
vi.mocked(extractPdfText).mockReturnValue(pdf.promise)
|
|
const a = pdfFile()
|
|
const { result } = renderHook(() => useFileProcessor())
|
|
|
|
let first!: Promise<void>
|
|
act(() => {
|
|
first = result.current.handleFileChange([a])
|
|
})
|
|
await act(async () => {
|
|
await result.current.handleFileChange([])
|
|
})
|
|
|
|
await act(async () => {
|
|
pdf.resolve("pdf text")
|
|
await first
|
|
})
|
|
expect(result.current.pdfData.has(a)).toBe(false)
|
|
expect(result.current.files).toEqual([])
|
|
})
|
|
})
|