diff options
Diffstat (limited to 'src/client/components/SyncStatusIndicator.test.tsx')
| -rw-r--r-- | src/client/components/SyncStatusIndicator.test.tsx | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/client/components/SyncStatusIndicator.test.tsx b/src/client/components/SyncStatusIndicator.test.tsx new file mode 100644 index 0000000..a607e11 --- /dev/null +++ b/src/client/components/SyncStatusIndicator.test.tsx @@ -0,0 +1,160 @@ +/** + * @vitest-environment jsdom + */ +import "fake-indexeddb/auto"; +import { cleanup, render, screen } from "@testing-library/react"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { SyncStatusIndicator } from "./SyncStatusIndicator"; + +// Mock the useSync hook +const mockUseSync = vi.fn(); +vi.mock("../stores", () => ({ + useSync: () => mockUseSync(), +})); + +// Mock the SyncStatus constant +vi.mock("../sync", () => ({ + SyncStatus: { + Idle: "idle", + Syncing: "syncing", + Error: "error", + }, +})); + +describe("SyncStatusIndicator", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + afterEach(() => { + cleanup(); + }); + + it("displays 'Synced' when online with no pending changes", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: false, + pendingCount: 0, + lastError: null, + status: "idle", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Synced")).toBeDefined(); + expect(screen.getByTestId("sync-status-indicator")).toBeDefined(); + }); + + it("displays 'Offline' when not online", () => { + mockUseSync.mockReturnValue({ + isOnline: false, + isSyncing: false, + pendingCount: 0, + lastError: null, + status: "idle", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Offline")).toBeDefined(); + }); + + it("displays 'Syncing...' when syncing", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: true, + pendingCount: 0, + lastError: null, + status: "syncing", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Syncing...")).toBeDefined(); + }); + + it("displays pending count when there are pending changes", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: false, + pendingCount: 5, + lastError: null, + status: "idle", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("5 pending")).toBeDefined(); + }); + + it("displays 'Sync error' when there is an error", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: false, + pendingCount: 0, + lastError: "Network error", + status: "error", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Sync error")).toBeDefined(); + }); + + it("shows error message in title when there is an error", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: false, + pendingCount: 0, + lastError: "Network error", + status: "error", + }); + + render(<SyncStatusIndicator />); + + const indicator = screen.getByTestId("sync-status-indicator"); + expect(indicator.getAttribute("title")).toBe("Network error"); + }); + + it("prioritizes offline status over other states", () => { + mockUseSync.mockReturnValue({ + isOnline: false, + isSyncing: true, + pendingCount: 5, + lastError: "Error", + status: "error", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Offline")).toBeDefined(); + }); + + it("prioritizes syncing status over pending and error", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: true, + pendingCount: 5, + lastError: null, + status: "syncing", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Syncing...")).toBeDefined(); + }); + + it("prioritizes error status over pending", () => { + mockUseSync.mockReturnValue({ + isOnline: true, + isSyncing: false, + pendingCount: 5, + lastError: "Network error", + status: "error", + }); + + render(<SyncStatusIndicator />); + + expect(screen.getByText("Sync error")).toBeDefined(); + }); +}); |
