Fixes #912 This PR implements disabling send button while approval is pending and addresses issue #912 <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Disable the chat send button while a proposal is awaiting approval, and re-enable it after approve or reject. Prevents accidental messages during pending changes. Addresses issue #912. - **New Features** - Track pending changes with isChangesPending based on the last assistant message’s approvalState. - Disable the send button when a proposal is pending (in addition to the existing empty input check). - Re-enable after approve/reject by refreshing the proposal and messages. - Added Playwright e2e tests for both approve and reject flows. <!-- End of auto-generated description by cubic. --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Disable the chat send button when a code proposal is pending approval and re-enable after approve/reject; add e2e coverage and update MCP flow. > > - **Frontend** > - `ChatInput.tsx`: Read `messages` from `chatMessagesAtom` and derive `disableSendButton` when the last assistant message (matching `proposal.messageId`) has no `approvalState` and `proposal.type === "code-proposal"`. > - Apply `disableSendButton` to the send button’s `disabled` condition (in addition to empty input/attachments). > - Ensure proposal/messages refresh after approve/reject. > - **Tests** > - Add Playwright tests `e2e-tests/chat_input.spec.ts` to verify send button disabled during pending proposal and re-enabled after approve or reject. > - Update `e2e-tests/mcp.spec.ts` to click "Approve" after granting consent. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b9b47bd6f547449cc5cf1d39a00e4e7fb5de1bcd. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Will Chen <willchen90@gmail.com>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import path from "path";
|
|
import { test } from "./helpers/test_helper";
|
|
import { expect } from "@playwright/test";
|
|
|
|
test("mcp - call calculator", async ({ po }) => {
|
|
await po.setUp();
|
|
await po.goToSettingsTab();
|
|
await po.page.getByRole("button", { name: "Tools (MCP)" }).click();
|
|
|
|
await po.page
|
|
.getByRole("textbox", { name: "My MCP Server" })
|
|
.fill("testing-mcp-server");
|
|
await po.page.getByRole("textbox", { name: "node" }).fill("node");
|
|
const testMcpServerPath = path.join(
|
|
__dirname,
|
|
"..",
|
|
"testing",
|
|
"fake-stdio-mcp-server.mjs",
|
|
);
|
|
console.log("testMcpServerPath", testMcpServerPath);
|
|
await po.page
|
|
.getByRole("textbox", { name: "path/to/mcp-server.js --flag" })
|
|
.fill(testMcpServerPath);
|
|
await po.page.getByRole("button", { name: "Add Server" }).click();
|
|
await po.page
|
|
.getByRole("button", { name: "Add Environment Variable" })
|
|
.click();
|
|
await po.page.getByRole("textbox", { name: "Key" }).fill("testKey1");
|
|
await po.page.getByRole("textbox", { name: "Value" }).fill("testValue1");
|
|
await po.page.getByRole("button", { name: "Save" }).click();
|
|
await po.goToAppsTab();
|
|
await po.selectChatMode("agent");
|
|
await po.sendPrompt("[call_tool=calculator_add]", {
|
|
skipWaitForCompletion: true,
|
|
});
|
|
|
|
// Wait for consent dialog to appear
|
|
const alwaysAllowButton = po.page.getByRole("button", {
|
|
name: "Always allow",
|
|
});
|
|
await expect(alwaysAllowButton).toBeVisible();
|
|
|
|
// Make sure the tool call doesn't execute until consent is given
|
|
await po.snapshotMessages();
|
|
await alwaysAllowButton.click();
|
|
await po.page.getByRole("button", { name: "Approve" }).click();
|
|
|
|
await po.sendPrompt("[dump]");
|
|
await po.snapshotServerDump("all-messages");
|
|
});
|