aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/client/components/SyncButton.test.tsx
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-12-07 23:37:31 +0900
committernsfisis <nsfisis@gmail.com>2025-12-07 23:37:31 +0900
commit445781bc40afee2c64f645abcfa2575b4218aa08 (patch)
treea23f93af761233b12d575da1f07fdf3184307b7b /src/client/components/SyncButton.test.tsx
parent0c042ac89fc0822fcbe09c48702857faa5494ae1 (diff)
downloadkioku-445781bc40afee2c64f645abcfa2575b4218aa08.tar.gz
kioku-445781bc40afee2c64f645abcfa2575b4218aa08.tar.zst
kioku-445781bc40afee2c64f645abcfa2575b4218aa08.zip
feat(client): add manual sync button
Add SyncButton component that allows users to manually trigger data synchronization. The button is disabled when offline or when sync is already in progress. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/client/components/SyncButton.test.tsx')
-rw-r--r--src/client/components/SyncButton.test.tsx145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/client/components/SyncButton.test.tsx b/src/client/components/SyncButton.test.tsx
new file mode 100644
index 0000000..c399284
--- /dev/null
+++ b/src/client/components/SyncButton.test.tsx
@@ -0,0 +1,145 @@
+/**
+ * @vitest-environment jsdom
+ */
+import "fake-indexeddb/auto";
+import { cleanup, fireEvent, render, screen } from "@testing-library/react";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+import { SyncButton } from "./SyncButton";
+
+// Mock the useSync hook
+const mockSync = vi.fn();
+const mockUseSync = vi.fn();
+vi.mock("../stores", () => ({
+ useSync: () => mockUseSync(),
+}));
+
+describe("SyncButton", () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ mockSync.mockResolvedValue({ success: true });
+ });
+
+ afterEach(() => {
+ cleanup();
+ });
+
+ it("renders sync button", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: true,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ expect(screen.getByTestId("sync-button")).toBeDefined();
+ expect(screen.getByText("Sync")).toBeDefined();
+ });
+
+ it("displays 'Syncing...' when syncing", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: true,
+ isSyncing: true,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ expect(screen.getByText("Syncing...")).toBeDefined();
+ });
+
+ it("is disabled when offline", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: false,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ expect(button).toHaveProperty("disabled", true);
+ });
+
+ it("is disabled when syncing", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: true,
+ isSyncing: true,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ expect(button).toHaveProperty("disabled", true);
+ });
+
+ it("is enabled when online and not syncing", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: true,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ expect(button).toHaveProperty("disabled", false);
+ });
+
+ it("calls sync when clicked", async () => {
+ mockUseSync.mockReturnValue({
+ isOnline: true,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ fireEvent.click(button);
+
+ expect(mockSync).toHaveBeenCalledTimes(1);
+ });
+
+ it("does not call sync when clicked while disabled", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: false,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ fireEvent.click(button);
+
+ expect(mockSync).not.toHaveBeenCalled();
+ });
+
+ it("shows tooltip when offline", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: false,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ expect(button.getAttribute("title")).toBe("Cannot sync while offline");
+ });
+
+ it("does not show tooltip when online", () => {
+ mockUseSync.mockReturnValue({
+ isOnline: true,
+ isSyncing: false,
+ sync: mockSync,
+ });
+
+ render(<SyncButton />);
+
+ const button = screen.getByTestId("sync-button");
+ expect(button.getAttribute("title")).toBeNull();
+ });
+});