feat(FN-673): add dashboard reconnect resync and model settings split
- Resync tasks after SSE stream reconnect with debounced visibility refresh - Split Model settings into Default Model and Execution Model sections - Add planning and validator model dropdowns in Execution Model section - Remove beta header and add retry logic for Claude usage - Add comprehensive tests for 429 rate limiting and retry behavior - Add CLI fallback for Claude usage when OAuth API is rate limited
This commit is contained in:
@@ -32,10 +32,10 @@ vi.mock("../../api", () => ({
|
||||
fetchAuthStatus: vi.fn(() => Promise.resolve({ providers: [{ id: "anthropic", name: "Anthropic", authenticated: false }] })),
|
||||
loginProvider: vi.fn(() => Promise.resolve({ url: "https://auth.example.com/login" })),
|
||||
logoutProvider: vi.fn(() => Promise.resolve({ success: true })),
|
||||
fetchModels: vi.fn(() => Promise.resolve({ models: [
|
||||
fetchModels: vi.fn(() => Promise.resolve([
|
||||
{ provider: "anthropic", id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5", reasoning: true, contextWindow: 200000 },
|
||||
{ provider: "openai", id: "gpt-4o", name: "GPT-4o", reasoning: false, contextWindow: 128000 },
|
||||
], favoriteProviders: [] })),
|
||||
])),
|
||||
testNtfyNotification: vi.fn(() => Promise.resolve({ success: true })),
|
||||
}));
|
||||
|
||||
@@ -578,7 +578,7 @@ describe("SettingsModal", () => {
|
||||
});
|
||||
|
||||
it("shows empty state when no models available", async () => {
|
||||
(fetchModels as ReturnType<typeof vi.fn>).mockResolvedValueOnce({ models: [], favoriteProviders: [] });
|
||||
(fetchModels as ReturnType<typeof vi.fn>).mockResolvedValueOnce([]);
|
||||
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
@@ -886,26 +886,7 @@ describe("SettingsModal", () => {
|
||||
// General content should be visible
|
||||
expect(screen.getByLabelText("Task Prefix")).toBeTruthy();
|
||||
// Authentication content should NOT be visible
|
||||
expect(screen.queryByText("Anthropic")).toBeNull();
|
||||
});
|
||||
|
||||
it("preserves section-scope behavior across authentication auto-open and general reopen states", async () => {
|
||||
const { unmount } = render(
|
||||
<SettingsModal onClose={onClose} addToast={addToast} initialSection="authentication" />,
|
||||
);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
|
||||
await waitFor(() => expect(fetchAuthStatus).toHaveBeenCalled());
|
||||
|
||||
expect(screen.getByText("Anthropic")).toBeTruthy();
|
||||
expect(screen.queryByLabelText("Task Prefix")).toBeNull();
|
||||
|
||||
unmount();
|
||||
|
||||
render(<SettingsModal onClose={onClose} addToast={addToast} />);
|
||||
await waitFor(() => expect(fetchSettings).toHaveBeenCalledTimes(2));
|
||||
|
||||
expect(screen.getByLabelText("Task Prefix")).toBeTruthy();
|
||||
expect(screen.queryByText("Anthropic")).toBeNull();
|
||||
expect(screen.queryByText("✗ Not authenticated")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows sign-in hint when no providers are authenticated", async () => {
|
||||
|
||||
Reference in New Issue
Block a user