150 lines
4.3 KiB
TypeScript
150 lines
4.3 KiB
TypeScript
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
import { useEffect } from "react";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { defaultSettingsState } from "@/lib/state/slices/settings/settings-slice";
|
|
import { STORAGE_KEYS } from "@/lib/settings/constants";
|
|
import { StateProvider, useAppStore } from "./state-provider";
|
|
|
|
function ShowMetricsPreference({ label }: { label: string }) {
|
|
const enabled = useAppStore((state) => state.userSettings.systemMetricsDisplay.showInTopbar);
|
|
return (
|
|
<div>
|
|
{label}:{enabled ? "on" : "off"}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function EnableMetricsFromNestedProvider() {
|
|
const setUserSettings = useAppStore((state) => state.setUserSettings);
|
|
const userSettings = useAppStore((state) => state.userSettings);
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
setUserSettings({
|
|
...userSettings,
|
|
systemMetricsDisplay: { showInTopbar: true },
|
|
loaded: true,
|
|
})
|
|
}
|
|
>
|
|
Enable metrics
|
|
</button>
|
|
);
|
|
}
|
|
|
|
function ObserveLastUsedCache({ onSeen }: { onSeen: (value: string | null) => void }) {
|
|
useEffect(() => {
|
|
onSeen(window.localStorage.getItem(STORAGE_KEYS.LAST_REPOSITORY_ID));
|
|
}, [onSeen]);
|
|
return null;
|
|
}
|
|
|
|
describe("StateProvider", () => {
|
|
beforeEach(() => {
|
|
window.localStorage.clear();
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("reuses the parent store for nested route providers", async () => {
|
|
render(
|
|
<StateProvider>
|
|
<ShowMetricsPreference label="root" />
|
|
<StateProvider
|
|
initialState={{
|
|
userSettings: {
|
|
...defaultSettingsState.userSettings,
|
|
systemMetricsDisplay: { showInTopbar: false },
|
|
loaded: true,
|
|
},
|
|
}}
|
|
>
|
|
<EnableMetricsFromNestedProvider />
|
|
</StateProvider>
|
|
</StateProvider>,
|
|
);
|
|
|
|
expect(screen.getByText("root:off")).toBeTruthy();
|
|
fireEvent.click(screen.getByRole("button", { name: "Enable metrics" }));
|
|
expect(await screen.findByText("root:on")).toBeTruthy();
|
|
});
|
|
|
|
it("syncs task-create last-used settings to localStorage without redundant writes", async () => {
|
|
function UpdateUnrelatedSetting() {
|
|
const setUserSettings = useAppStore((state) => state.setUserSettings);
|
|
const userSettings = useAppStore((state) => state.userSettings);
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
setUserSettings({
|
|
...userSettings,
|
|
showReleaseNotification: !userSettings.showReleaseNotification,
|
|
})
|
|
}
|
|
>
|
|
Toggle unrelated
|
|
</button>
|
|
);
|
|
}
|
|
|
|
const setItemSpy = vi.spyOn(Storage.prototype, "setItem");
|
|
render(
|
|
<StateProvider
|
|
initialState={{
|
|
userSettings: {
|
|
...defaultSettingsState.userSettings,
|
|
loaded: true,
|
|
taskCreateLastUsed: {
|
|
repositoryId: "repo-1",
|
|
branch: "main",
|
|
agentProfileId: "agent-1",
|
|
executorProfileId: "exec-1",
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
<UpdateUnrelatedSetting />
|
|
</StateProvider>,
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(window.localStorage.getItem(STORAGE_KEYS.LAST_REPOSITORY_ID)).toBe(
|
|
JSON.stringify("repo-1"),
|
|
);
|
|
});
|
|
const writesAfterInitialSync = setItemSpy.mock.calls.length;
|
|
|
|
fireEvent.click(screen.getByRole("button", { name: "Toggle unrelated" }));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByRole("button", { name: "Toggle unrelated" })).toBeTruthy();
|
|
});
|
|
expect(setItemSpy).toHaveBeenCalledTimes(writesAfterInitialSync);
|
|
});
|
|
|
|
it("primes task-create last-used localStorage before child effects run", () => {
|
|
const onSeen = vi.fn();
|
|
render(
|
|
<StateProvider
|
|
initialState={{
|
|
userSettings: {
|
|
...defaultSettingsState.userSettings,
|
|
loaded: true,
|
|
taskCreateLastUsed: {
|
|
repositoryId: "repo-1",
|
|
branch: "main",
|
|
agentProfileId: "agent-1",
|
|
executorProfileId: "exec-1",
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
<ObserveLastUsedCache onSeen={onSeen} />
|
|
</StateProvider>,
|
|
);
|
|
|
|
expect(onSeen).toHaveBeenCalledWith(JSON.stringify("repo-1"));
|
|
});
|
|
});
|