feat(FN-2120): merge fusion/fn-2120
This commit is contained in:
@@ -453,7 +453,6 @@ describe("MissionInterviewModal", () => {
|
||||
favoriteProviders: [],
|
||||
favoriteModels: [],
|
||||
});
|
||||
mockUpdateGlobalSettings.mockResolvedValue({});
|
||||
|
||||
renderModal();
|
||||
|
||||
@@ -477,9 +476,38 @@ describe("MissionInterviewModal", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("persists model favorite toggle via updateGlobalSettings", async () => {
|
||||
mockFetchModels.mockResolvedValue({
|
||||
models: mockModelsWithFavorites.models,
|
||||
favoriteProviders: [],
|
||||
favoriteModels: [],
|
||||
});
|
||||
|
||||
renderModal();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockFetchModels).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Planning Model" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(document.body.querySelector('[data-testid="model-combobox-portal"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
const portal = document.body.querySelector('[data-testid="model-combobox-portal"]')!;
|
||||
const addModelButton = within(portal).getByRole("button", { name: "Add Claude Sonnet 4.5 to favorites" });
|
||||
fireEvent.click(addModelButton);
|
||||
|
||||
expect(mockUpdateGlobalSettings).toHaveBeenCalledWith({
|
||||
favoriteProviders: [],
|
||||
favoriteModels: ["anthropic/claude-sonnet-4-5"],
|
||||
});
|
||||
});
|
||||
|
||||
it("rolls back local favorite state when updateGlobalSettings fails", async () => {
|
||||
mockFetchModels.mockResolvedValue(mockModelsWithFavorites);
|
||||
vi.mocked(api.updateGlobalSettings).mockRejectedValueOnce(new Error("Network error"));
|
||||
mockUpdateGlobalSettings.mockRejectedValueOnce(new Error("Network error"));
|
||||
|
||||
renderModal();
|
||||
|
||||
|
||||
@@ -1077,12 +1077,8 @@ describe("NewAgentDialog", () => {
|
||||
});
|
||||
|
||||
describe("model favorites persistence", () => {
|
||||
it("calls updateGlobalSettings when toggling provider favorite", async () => {
|
||||
mockFetchModels.mockResolvedValue({
|
||||
models: MOCK_MODELS_RESPONSE.models,
|
||||
favoriteProviders: [],
|
||||
favoriteModels: [],
|
||||
});
|
||||
it("persists provider favorite toggle via updateGlobalSettings", async () => {
|
||||
mockFetchModels.mockResolvedValue(MOCK_MODELS_RESPONSE);
|
||||
|
||||
render(
|
||||
<NewAgentDialog isOpen={true} onClose={mockOnClose} onCreated={mockOnCreated} />,
|
||||
@@ -1096,70 +1092,17 @@ describe("NewAgentDialog", () => {
|
||||
await user.click(screen.getByText("Next"));
|
||||
|
||||
const portal = await openModelDropdown();
|
||||
fireEvent.click(within(portal).getByRole("button", { name: "Add anthropic to favorites" }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdateGlobalSettings).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("persists provider favorite toggle to global settings", async () => {
|
||||
mockFetchModels.mockResolvedValue({
|
||||
models: MOCK_MODELS_RESPONSE.models,
|
||||
favoriteProviders: [],
|
||||
favoriteModels: [],
|
||||
});
|
||||
|
||||
render(
|
||||
<NewAgentDialog isOpen={true} onClose={mockOnClose} onCreated={mockOnCreated} />,
|
||||
);
|
||||
|
||||
await waitFor(() => expect(mockFetchModels).toHaveBeenCalledOnce());
|
||||
|
||||
const user = userEvent.setup();
|
||||
const nameInput = screen.getByLabelText(/Name/);
|
||||
await user.type(nameInput, "Test Agent");
|
||||
await user.click(screen.getByText("Next"));
|
||||
|
||||
const portal = await openModelDropdown();
|
||||
fireEvent.click(within(portal).getByRole("button", { name: "Add anthropic to favorites" }));
|
||||
|
||||
expect(mockUpdateGlobalSettings).toHaveBeenCalledWith({
|
||||
favoriteProviders: ["anthropic"],
|
||||
favoriteModels: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("persists model favorite toggle to global settings", async () => {
|
||||
mockFetchModels.mockResolvedValue({
|
||||
models: MOCK_MODELS_RESPONSE.models,
|
||||
favoriteProviders: [],
|
||||
favoriteModels: [],
|
||||
});
|
||||
|
||||
render(
|
||||
<NewAgentDialog isOpen={true} onClose={mockOnClose} onCreated={mockOnCreated} />,
|
||||
);
|
||||
|
||||
await waitFor(() => expect(mockFetchModels).toHaveBeenCalledOnce());
|
||||
|
||||
const user = userEvent.setup();
|
||||
const nameInput = screen.getByLabelText(/Name/);
|
||||
await user.type(nameInput, "Test Agent");
|
||||
await user.click(screen.getByText("Next"));
|
||||
|
||||
const portal = await openModelDropdown();
|
||||
fireEvent.click(within(portal).getByRole("button", { name: "Add Claude Sonnet 4.5 to favorites" }));
|
||||
fireEvent.click(within(portal).getByRole("button", { name: "Remove anthropic from favorites" }));
|
||||
|
||||
expect(mockUpdateGlobalSettings).toHaveBeenCalledWith({
|
||||
favoriteProviders: [],
|
||||
favoriteModels: ["anthropic/claude-sonnet-4-5"],
|
||||
favoriteModels: expect.any(Array),
|
||||
});
|
||||
});
|
||||
|
||||
it("rolls back local favorite state when updateGlobalSettings fails", async () => {
|
||||
mockFetchModels.mockResolvedValue(MOCK_MODELS_RESPONSE);
|
||||
vi.mocked(apiModule.updateGlobalSettings).mockRejectedValueOnce(new Error("Network error"));
|
||||
mockUpdateGlobalSettings.mockRejectedValueOnce(new Error("Network error"));
|
||||
|
||||
render(
|
||||
<NewAgentDialog isOpen={true} onClose={mockOnClose} onCreated={mockOnCreated} />,
|
||||
@@ -1179,7 +1122,7 @@ describe("NewAgentDialog", () => {
|
||||
fireEvent.click(removeButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(apiModule.updateGlobalSettings).toHaveBeenCalled();
|
||||
expect(mockUpdateGlobalSettings).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const portalAfterRollback = document.body.querySelector('[data-testid="model-combobox-portal"]') as HTMLElement;
|
||||
|
||||
@@ -255,12 +255,12 @@ describe("Proxy routes", () => {
|
||||
});
|
||||
|
||||
describe("POST /api/proxy/:nodeId/* body forwarding", () => {
|
||||
it("forwards POST body with JSON Content-Type", async () => {
|
||||
it("forwards body for POST requests with Content-Type", async () => {
|
||||
const node = createMockRemoteNode();
|
||||
mockGetNode.mockResolvedValue(node);
|
||||
|
||||
const requestBody = JSON.stringify({ key: "value" });
|
||||
const rawBody = Buffer.from(requestBody);
|
||||
const postBody = JSON.stringify({ settings: { theme: "dark" } });
|
||||
const rawBody = Buffer.from(postBody);
|
||||
const mockResponse = createMockResponse(200, { "content-type": "application/json" }, { ok: true });
|
||||
const mockFetch = vi.fn().mockResolvedValue(mockResponse);
|
||||
|
||||
@@ -271,23 +271,26 @@ describe("Proxy routes", () => {
|
||||
const res = await request(
|
||||
app,
|
||||
"POST",
|
||||
"/api/proxy/remote-node/settings/sync",
|
||||
requestBody,
|
||||
"/api/proxy/remote-node/settings/sync-receive",
|
||||
postBody,
|
||||
{ "Content-Type": "application/json" },
|
||||
rawBody,
|
||||
);
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect(mockFetch).toHaveBeenCalledWith(
|
||||
expect.stringContaining("http://remote:4040/settings/sync"),
|
||||
"http://remote:4040/settings/sync-receive",
|
||||
expect.objectContaining({
|
||||
method: "POST",
|
||||
headers: expect.objectContaining({
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: rawBody,
|
||||
}),
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]?.[1] as { body?: Buffer };
|
||||
expect(fetchCall.body).toBeDefined();
|
||||
expect(fetchCall.body?.toString()).toBe(postBody);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user