import { create } from "@bufbuild/protobuf";
import { fireEvent, render, screen } from "@testing-library/react";
import { beforeAll, describe, expect, it, vi } from "vitest";
import AttachmentListEditor from "@/components/MemoMetadata/Attachment/AttachmentListEditor";
import { AttachmentSchema } from "@/types/proto/api/v1/attachment_service_pb";
const image = create(AttachmentSchema, {
name: "attachments/photo",
filename: "photo.png",
type: "image/png",
size: 128n,
});
beforeAll(() => {
Object.defineProperty(window, "matchMedia", {
writable: true,
value: () => ({
matches: false,
addEventListener: () => undefined,
removeEventListener: () => undefined,
}),
});
});
describe("attachment inline placement actions", () => {
it("offers insertion for an attachment-only image", () => {
const onInsertAttachments = vi.fn();
render(
,
);
fireEvent.click(screen.getByRole("button", { name: "Insert image" }));
expect(onInsertAttachments).toHaveBeenCalledWith([image]);
expect(screen.getByRole("button", { name: "Remove attachment" })).toBeInTheDocument();
});
it("hides an inline image and restores it after its Markdown reference is removed", () => {
const props = {
attachments: [image],
onAttachmentsChange: vi.fn(),
};
const { rerender } = render();
expect(screen.queryByText("Attachments")).not.toBeInTheDocument();
expect(screen.queryByText("photo.png")).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Remove attachment" })).not.toBeInTheDocument();
rerender();
expect(screen.getByText(/Attachments/)).toBeInTheDocument();
expect(screen.getByText("photo.png")).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Remove attachment" })).toBeInTheDocument();
});
it("preserves hidden inline attachments when visible attachments are reordered", () => {
const second = create(AttachmentSchema, { ...image, name: "attachments/second", filename: "second.png" });
const third = create(AttachmentSchema, { ...image, name: "attachments/third", filename: "third.png" });
const onAttachmentsChange = vi.fn();
render(
,
);
fireEvent.click(screen.getAllByRole("button", { name: "Move attachment down" })[0]!);
expect(onAttachmentsChange).toHaveBeenCalledWith([image, third, second]);
});
it("does not offer inline placement for external images", () => {
render(
,
);
expect(screen.queryByRole("button", { name: "Insert image" })).not.toBeInTheDocument();
});
it("shows local inline-upload status and prevents removal while uploading", () => {
const localImage = {
file: new File(["image"], "local.png", { type: "image/png" }),
previewUrl: "blob:local",
origin: "upload" as const,
};
render(
,
);
expect(screen.getByText("Uploading to content")).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Insert image" })).toBeDisabled();
expect(screen.queryByRole("button", { name: "Remove attachment" })).not.toBeInTheDocument();
});
});