Files
AgentCompany/tests/unit/store.test.ts
T

239 lines
8.0 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
import { useAppStore } from "@renderer/state/store";
import { assembleProfileSnapshot } from "@renderer/state/snapshot-sections";
import type { ProfileSnapshot } from "@shared/types";
// Mock window.agentCompany for refreshSnapshot tests. Sidebar badges
// no longer traverse IPC — they are derived from the snapshot in
// `@shared/sidebar-badges`, so there is nothing store-level to mock
// for them.
const mockLoadSnapshot = vi.fn();
vi.stubGlobal("window", {
agentCompany: {
loadSnapshot: mockLoadSnapshot,
},
});
describe("useAppStore", () => {
beforeEach(() => {
// Reset store to initial state before each test
useAppStore.setState(useAppStore.getInitialState());
vi.clearAllMocks();
});
it("is created without errors and has all 6 slice properties", () => {
const state = useAppStore.getState();
// NavigationSlice
expect(state).toHaveProperty("section");
expect(state).toHaveProperty("setSection");
expect(state).toHaveProperty("commandPaletteOpen");
expect(state).toHaveProperty("toggleCommandPalette");
// CompanySlice
expect(state).toHaveProperty("snapshot");
expect(state).toHaveProperty("snapshotSections");
expect(state).toHaveProperty("setSnapshot");
expect(state).toHaveProperty("refreshSnapshot");
// SelectionSlice
expect(state).toHaveProperty("selectedTaskId");
expect(state).toHaveProperty("clearCompanyScopedSelections");
// UiSlice
expect(state).toHaveProperty("locale");
expect(state).toHaveProperty("setLocale");
// CommunicationSlice - exists (even if minimal)
expect(state).toBeDefined();
// SocialSlice
expect(state).toHaveProperty("socialAccounts");
expect(state).toHaveProperty("setSocialAccounts");
});
it("NavigationSlice.setSection('tasks') updates section to 'tasks'", () => {
expect(useAppStore.getState().section).toBe("overview");
useAppStore.getState().setSection("tasks");
expect(useAppStore.getState().section).toBe("tasks");
});
it("NavigationSlice.toggleCommandPalette() toggles commandPaletteOpen and clears search on close", () => {
expect(useAppStore.getState().commandPaletteOpen).toBe(false);
// Open
useAppStore.getState().toggleCommandPalette();
expect(useAppStore.getState().commandPaletteOpen).toBe(true);
// Set some search state
useAppStore.getState().setCommandPaletteSearch("test");
useAppStore.getState().setSelectedPaletteIndex(3);
expect(useAppStore.getState().commandPaletteSearch).toBe("test");
expect(useAppStore.getState().selectedPaletteIndex).toBe(3);
// Close -- should clear search and index
useAppStore.getState().toggleCommandPalette();
expect(useAppStore.getState().commandPaletteOpen).toBe(false);
expect(useAppStore.getState().commandPaletteSearch).toBe("");
expect(useAppStore.getState().selectedPaletteIndex).toBe(0);
});
it("NavigationSlice.navigateTo('agents', 'agent-123') sets section to 'agents' and selectedAgentId to 'agent-123'", () => {
useAppStore.getState().navigateTo("agents", "agent-123");
expect(useAppStore.getState().section).toBe("agents");
expect(useAppStore.getState().selectedAgentId).toBe("agent-123");
});
it("SelectionSlice.clearCompanyScopedSelections() nulls all selection IDs", () => {
// Set some selections
useAppStore.getState().setSelectedTaskId("task-1");
useAppStore.getState().setSelectedAgentId("agent-1");
useAppStore.getState().setSelectedApprovalId("approval-1");
useAppStore.getState().setSelectedRunId("run-1");
useAppStore.getState().setSelectedGoalId("goal-1");
useAppStore.getState().setSelectedProjectId("project-1");
useAppStore.getState().setSelectedWorkspaceId("workspace-1");
useAppStore.getState().setSelectedCommunicationEntityId("comm-1");
useAppStore.getState().setSelectedConnectorId("conn-1");
useAppStore.getState().clearCompanyScopedSelections();
const state = useAppStore.getState();
expect(state.selectedTaskId).toBeNull();
expect(state.selectedAgentId).toBeNull();
expect(state.selectedApprovalId).toBeNull();
expect(state.selectedRunId).toBeNull();
expect(state.selectedGoalId).toBeNull();
expect(state.selectedProjectId).toBeNull();
expect(state.selectedWorkspaceId).toBeNull();
expect(state.selectedCommunicationEntityId).toBeNull();
// Connector is NOT cleared per spec
expect(state.selectedConnectorId).toBe("conn-1");
});
it("CompanySlice.setSnapshot(mockSnapshot) stores snapshot correctly", () => {
const mockSnapshot: ProfileSnapshot = {
currentCompanyId: "company-1",
profilePath: "/test/path",
updatesEnabled: true,
theme: "system",
locale: "en",
backend: { secretBackend: "safe_storage" },
companies: [],
connectors: [],
workspaces: [],
agents: [],
goals: [],
projects: [],
tasks: [],
approvals: [],
runs: [],
costs: [],
activity: [],
secrets: [],
comments: [],
socialAccounts: [],
meetings: [],
documents: [],
workProducts: [],
knowledgeBase: [],
sprints: [],
automationRules: [],
agentMessages: [],
workflows: [],
};
expect(useAppStore.getState().snapshot).toBeNull();
useAppStore.getState().setSnapshot(mockSnapshot);
expect(useAppStore.getState().snapshot).toEqual(mockSnapshot);
expect(useAppStore.getState().snapshotSections?.metadata.profilePath).toBe("/test/path");
expect(useAppStore.getState().snapshotSections?.catalog.companies).toEqual([]);
expect(useAppStore.getState().snapshotSections?.company.tasks).toEqual([]);
expectSnapshotSectionsMatchSnapshot();
});
it("CompanySlice.refreshSnapshot() calls window.agentCompany.loadSnapshot()", async () => {
const mockSnapshot: ProfileSnapshot = {
currentCompanyId: "company-1",
profilePath: "/test/path",
updatesEnabled: true,
theme: "system",
locale: "en",
backend: { secretBackend: "safe_storage" },
companies: [],
connectors: [],
workspaces: [],
agents: [],
goals: [],
projects: [],
tasks: [],
approvals: [],
runs: [],
costs: [],
activity: [],
secrets: [],
comments: [],
socialAccounts: [],
meetings: [],
documents: [],
workProducts: [],
knowledgeBase: [],
sprints: [],
automationRules: [],
agentMessages: [],
workflows: [],
};
mockLoadSnapshot.mockResolvedValue({ ok: true, data: mockSnapshot });
await useAppStore.getState().refreshSnapshot();
expect(mockLoadSnapshot).toHaveBeenCalledTimes(1);
expect(useAppStore.getState().snapshot).toEqual(mockSnapshot);
expect(useAppStore.getState().snapshotSections?.metadata.currentCompanyId).toBe("company-1");
expectSnapshotSectionsMatchSnapshot();
});
it("UiSlice.setLocale('zh') updates locale to 'zh'", () => {
expect(useAppStore.getState().locale).toBe("en");
useAppStore.getState().setLocale("zh");
expect(useAppStore.getState().locale).toBe("zh");
});
it("SocialSlice.setSocialAccounts([account]) stores accounts", () => {
const account = {
id: "acc-1",
companyId: "company-1",
platform: "twitter" as const,
accountName: "@test",
displayName: "Test",
profileUrl: "https://twitter.com/test",
credentialSecretId: null,
status: "active" as const,
requireApproval: false,
metadataJson: "{}",
lastUsedAt: null,
createdAt: "2026-01-01",
updatedAt: "2026-01-01",
};
expect(useAppStore.getState().socialAccounts).toEqual([]);
useAppStore.getState().setSocialAccounts([account]);
expect(useAppStore.getState().socialAccounts).toEqual([account]);
});
});
function expectSnapshotSectionsMatchSnapshot() {
const { snapshot, snapshotSections } = useAppStore.getState();
expect(snapshot).toEqual(snapshotSections ? assembleProfileSnapshot(snapshotSections) : null);
}