Files
SnapOtter/tests/unit/web/home-page-redirect.test.tsx
T
SnapOtter 649ad5db9e test: massive test coverage expansion (+1,437 tests, 22 new files)
Expand test coverage across all layers via 14 parallel agents:

Unit tests (3,378 total, +534):
- First-ever AI sidecar tests (157 tests covering bridge lifecycle, all 12 tool modules)
- API route infrastructure (auth, pipeline, batch, settings, teams, roles, audit, api-keys, files, docs)
- Lib coverage improvements (audit 7%->95%, worker-pool 33%->100%)
- Web store/lib gap fills (features-store, tool-registry)

Integration tests (4,403 total, +903):
- Expanded 19 tool test files with parameter variations, format edge cases, boundary values
- Cross-format matrix: 290 tests covering 14 tools x 17 formats
- Adversarial/edge cases: 63 tests for extreme inputs, concurrent requests, corrupted files

E2E-Docker (125 new tests):
- Expanded 8 spec files + 1 new file covering all 49 tools
- Added HEIC/format handling, auth failures, download verification

GUI E2E (expanded 28 spec files):
- Navigation, responsive layout, keyboard shortcuts
- All 51 tool UIs with settings, processing, display modes
- Batch/pipeline workflows, settings/RBAC, visual regression
- Resilience, accessibility (ARIA, contrast, focus), performance budgets
2026-05-09 09:02:29 +08:00

159 lines
4.0 KiB
TypeScript

// @vitest-environment jsdom
import type React from "react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
let settingsState = {
fetch: vi.fn(),
defaultToolView: "sidebar" as "sidebar" | "fullscreen",
loaded: false,
};
vi.mock("@/stores/settings-store", () => ({
useSettingsStore: () => settingsState,
}));
let fileState = {
setFiles: vi.fn(),
files: [] as File[],
reset: vi.fn(),
originalBlobUrl: null as string | null,
selectedFileName: null as string | null,
selectedFileSize: 0,
currentEntry: null,
};
vi.mock("@/stores/file-store", () => ({
useFileStore: () => fileState,
}));
vi.mock("@/stores/features-store", () => ({
useFeaturesStore: () => ({
fetch: vi.fn(),
bundles: [],
installing: {},
queued: [],
}),
}));
vi.mock("@/components/layout/app-layout", () => ({
AppLayout: ({ children }: React.PropsWithChildren) => (
<div data-testid="app-layout">{children}</div>
),
}));
vi.mock("@/components/common/image-viewer", () => ({
ImageViewer: () => null,
}));
vi.mock("@/components/common/multi-image-viewer", () => ({
MultiImageViewer: () => null,
}));
vi.mock("@/lib/icon-map", () => ({
ICON_MAP: new Proxy(
{},
{
get: () => (props: { className?: string }) => <span {...props} />,
},
),
}));
import { cleanup, render } from "@testing-library/react";
import { MemoryRouter, Route, Routes, useLocation } from "react-router-dom";
import { HomePage } from "@/pages/home-page";
let currentPath = "/";
function LocationSpy() {
const location = useLocation();
currentPath = location.pathname;
return null;
}
function renderInRouter(initialPath = "/") {
currentPath = initialPath;
return render(
<MemoryRouter initialEntries={[initialPath]}>
<LocationSpy />
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/fullscreen" element={<div data-testid="fullscreen-page" />} />
</Routes>
</MemoryRouter>,
);
}
afterEach(cleanup);
// Tests are ordered intentionally: the module-level `hasAppliedDefaultRedirect`
// flag starts false and is set true by the "redirects on first mount" test.
// Tests before it verify conditions that independently prevent the redirect
// (so the flag stays false). The final test verifies the flag prevents repeat redirects.
describe("HomePage default view redirect", () => {
beforeEach(() => {
settingsState = {
fetch: vi.fn(),
defaultToolView: "sidebar",
loaded: false,
};
fileState = {
setFiles: vi.fn(),
files: [],
reset: vi.fn(),
originalBlobUrl: null,
selectedFileName: null,
selectedFileSize: 0,
currentEntry: null,
};
});
it("does NOT redirect when settings have not loaded yet", () => {
settingsState.loaded = false;
settingsState.defaultToolView = "fullscreen";
renderInRouter("/");
expect(currentPath).toBe("/");
});
it("does NOT redirect when default view is sidebar", () => {
settingsState.loaded = true;
settingsState.defaultToolView = "sidebar";
renderInRouter("/");
expect(currentPath).toBe("/");
});
it("does NOT redirect when files are loaded even with fullscreen default", () => {
settingsState.loaded = true;
settingsState.defaultToolView = "fullscreen";
fileState.files = [new File([new ArrayBuffer(1024)], "test.png", { type: "image/png" })];
fileState.originalBlobUrl = "blob:fake-url";
fileState.selectedFileName = "test.png";
fileState.selectedFileSize = 1024;
renderInRouter("/");
expect(currentPath).toBe("/");
});
it("redirects to /fullscreen on first mount when default view is fullscreen", () => {
settingsState.loaded = true;
settingsState.defaultToolView = "fullscreen";
renderInRouter("/");
expect(currentPath).toBe("/fullscreen");
});
it("does NOT redirect on subsequent mounts after initial redirect (issue #128)", () => {
settingsState.loaded = true;
settingsState.defaultToolView = "fullscreen";
renderInRouter("/");
expect(currentPath).toBe("/");
});
});