Files
SnapOtter/tests/unit/web/review-panel-saved-state.test.tsx
T
SnapOtterandGitHub a23158d968 feat(files): add save-as-new vs overwrite choice for library file edits (#564)
Editing a file from the library used to silently supersede it: the worker auto-saved every result as a new version and the leaf-only listing hid the original, which read as a destructive overwrite. Tool pages now show a per-edit choice for library-sourced files. The default saves the result as an independent new file and keeps the original; picking overwrite keeps the old superseding-version behavior.

The client sends a saveMode multipart field next to fileId, validated with a 400 on unknown values, and autoSaveToLibrary branches on it. Every hand-written route that honors fileId parses the field the same way as the factory. The review panel shows where an auto-saved result went instead of offering a second, duplicate save. Tools whose route or submitter ignores fileId keep the selector hidden via a shared unsupported-tools set, and the choice resets to the non-destructive default whenever a new file is staged.

Closes #495
2026-07-18 11:36:08 +08:00

62 lines
2.0 KiB
TypeScript

// @vitest-environment jsdom
import { cleanup, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { afterEach, describe, expect, it, vi } from "vitest";
vi.mock("@/lib/analytics", () => ({
track: vi.fn(),
}));
vi.mock("@/components/feedback/tool-feedback-prompt", () => ({
ToolFeedbackPrompt: () => null,
}));
import { ReviewPanel } from "@/components/common/review-panel";
function renderPanel(props: Partial<Parameters<typeof ReviewPanel>[0]> = {}) {
return render(
<MemoryRouter>
<ReviewPanel
filename="photo_resize.png"
fileSize={512}
fileType="PNG"
originalSize={1024}
downloadUrl="/api/v1/download/job-1/photo_resize.png"
onUndo={() => {}}
onStartOver={() => {}}
currentToolId="resize"
{...props}
/>
</MemoryRouter>,
);
}
describe("ReviewPanel library saved state (issue #495)", () => {
afterEach(() => {
cleanup();
});
it("shows the manual save link when the result was not auto-saved", () => {
renderPanel();
expect(screen.getByRole("button", { name: /save to files/i })).toBeDefined();
expect(screen.queryByRole("link", { name: /view in files/i })).toBeNull();
});
it("replaces the manual save link with the saved indicator after an auto-save", () => {
renderPanel({ savedLibraryFileId: "lib-copy" });
expect(screen.getByText("Saved to Files")).toBeDefined();
expect(screen.getByRole("link", { name: /view in files/i })).toBeDefined();
// The manual save button must be gone: clicking it would create a duplicate
expect(screen.queryByRole("button", { name: /save to files/i })).toBeNull();
});
it("shows neither control for data-output tools", () => {
renderPanel({ currentToolId: "ocr", savedLibraryFileId: "lib-copy" });
expect(screen.queryByRole("button", { name: /save to files/i })).toBeNull();
expect(screen.queryByRole("link", { name: /view in files/i })).toBeNull();
});
});