feat : give error code when upload fail
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
// @vitest-environment happy-dom
|
||||
import { act, createElement } from "react";
|
||||
import { createRoot, type Root } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({ error: vi.fn(), success: vi.fn() }));
|
||||
vi.mock("sonner", () => ({ toast: mocks }));
|
||||
import { MediaUploader } from "./media-uploader";
|
||||
|
||||
let container: HTMLDivElement;
|
||||
let root: Root;
|
||||
const fetchUpload = vi.fn();
|
||||
const onReady = vi.fn();
|
||||
const onUploadingChange = vi.fn();
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
||||
vi.stubGlobal("fetch", fetchUpload);
|
||||
container = document.createElement("div");
|
||||
document.body.append(container);
|
||||
root = createRoot(container);
|
||||
await act(async () => root.render(createElement(MediaUploader, { onReady, onUploadingChange })));
|
||||
});
|
||||
afterEach(async () => {
|
||||
await act(async () => root.unmount());
|
||||
container.remove();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
async function selectImage() {
|
||||
const input = container.querySelector("input")!;
|
||||
Object.defineProperty(input, "files", { configurable: true, value: [new File(["image"], "test.png", { type: "image/png" })] });
|
||||
await act(async () => input.dispatchEvent(new Event("change", { bubbles: true })));
|
||||
}
|
||||
|
||||
describe("media upload responses", () => {
|
||||
it("reports HTTP 503 when the network replaces the API error with HTML", async () => {
|
||||
fetchUpload.mockResolvedValueOnce(new Response("<!doctype html><html>503 Service Unavailable</html>", {
|
||||
status: 503, headers: { "Content-Type": "text/html" },
|
||||
}));
|
||||
await selectImage();
|
||||
expect(mocks.error).toHaveBeenCalledWith(expect.stringContaining("HTTP 503"));
|
||||
expect(onReady).not.toHaveBeenCalled();
|
||||
expect(onUploadingChange.mock.calls).toEqual([[true], [false]]);
|
||||
expect(container.querySelector("input")?.disabled).toBe(false);
|
||||
});
|
||||
|
||||
it("preserves JSON API error details", async () => {
|
||||
fetchUpload.mockResolvedValueOnce(Response.json({ error: "uploads-busy" }, { status: 429 }));
|
||||
await selectImage();
|
||||
expect(mocks.error).toHaveBeenCalledWith("uploads-busy");
|
||||
expect(onReady).not.toHaveBeenCalled();
|
||||
expect(container.querySelector("input")?.disabled).toBe(false);
|
||||
});
|
||||
|
||||
it("passes a successful upload to the editor", async () => {
|
||||
const media = { id: "media", url: "https://cdn.test/image.png", fileName: "test.png", width: 1, height: 1 };
|
||||
fetchUpload.mockResolvedValueOnce(Response.json(media, { status: 201 }));
|
||||
await selectImage();
|
||||
expect(fetchUpload).toHaveBeenCalledWith("/api/admin/media", expect.objectContaining({ method: "POST", body: expect.any(FormData) }));
|
||||
expect(onReady).toHaveBeenCalledExactlyOnceWith(media);
|
||||
expect(mocks.success).toHaveBeenCalledTimes(1);
|
||||
expect(onUploadingChange.mock.calls).toEqual([[true], [false]]);
|
||||
});
|
||||
});
|
||||
@@ -49,8 +49,11 @@ export function MediaUploader({
|
||||
method: "POST",
|
||||
body,
|
||||
});
|
||||
const result = await response.json() as UploadedMedia & { error?: string };
|
||||
if (!response.ok) throw new Error(result.error || "upload");
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => null) as { error?: string } | null;
|
||||
throw new Error(error?.error || `อัปโหลดไม่สำเร็จ (HTTP ${response.status}) กรุณาลองอีกครั้ง`);
|
||||
}
|
||||
const result = await response.json() as UploadedMedia;
|
||||
onReady(result);
|
||||
toast.success("อัปโหลดรูปภาพแล้ว");
|
||||
} catch (cause) {
|
||||
|
||||
Reference in New Issue
Block a user