mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 00:53:38 +02:00
fix(mcp): preserve write opt-out across organization selection
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
024de57978
commit
dba2caf2f6
3 files changed
+14
-3
No files matched your search
@@ -20,7 +20,10 @@ vi.mock("../api/client", () => ({ api: {
|
||||
get: vi.fn(async () => ({
|
||||
id: route.id, clientName: "Assistant", redirectOrigin: "https://assistant.example.test",
|
||||
requestedWrite: route.requestedWrite, offlineAccess: true, requiresSignIn: false, requestedCompanyId: route.companyId,
|
||||
companies: route.unavailable ? [] : [{ id: route.companyId ?? "company-one", name: "Acme Research", logoUrl: "/api/assets/acme-logo/content", canWrite: route.canWrite }], setupUrl: null,
|
||||
companies: route.unavailable ? [] : [
|
||||
{ id: route.companyId ?? "company-one", name: "Acme Research", logoUrl: "/api/assets/acme-logo/content", canWrite: route.canWrite },
|
||||
...(!route.companyId ? [{ id: "company-two", name: "Design Partners", logoUrl: null, canWrite: true }] : []),
|
||||
], setupUrl: null,
|
||||
})),
|
||||
post: vi.fn(() => new Promise(() => {})),
|
||||
} }));
|
||||
@@ -45,7 +48,7 @@ function setup() {
|
||||
};
|
||||
}
|
||||
|
||||
it("defaults eligible writes on after selection, preserves opt-out on refetch, and submits read-only consent", async () => {
|
||||
it("defaults eligible writes on and preserves opt-out across organization changes and refetch", async () => {
|
||||
const page = setup();
|
||||
try {
|
||||
await vi.waitFor(() => expect(page.container.querySelector('input[type="radio"]')).not.toBeNull());
|
||||
@@ -54,6 +57,10 @@ it("defaults eligible writes on after selection, preserves opt-out on refetch, a
|
||||
flushSync(() => (page.container.querySelector('input[type="radio"]') as HTMLInputElement).click());
|
||||
expect(page.checkbox().getAttribute("aria-checked")).toBe("true");
|
||||
flushSync(() => page.checkbox().click());
|
||||
flushSync(() => (page.container.querySelector('input[value="company-two"]') as HTMLInputElement).click());
|
||||
expect(page.checkbox().getAttribute("aria-checked")).toBe("false");
|
||||
flushSync(() => (page.container.querySelector('input[value="company-one"]') as HTMLInputElement).click());
|
||||
expect(page.checkbox().getAttribute("aria-checked")).toBe("false");
|
||||
await page.client.invalidateQueries({ queryKey: ["mcp-request", route.id] });
|
||||
expect(page.checkbox().getAttribute("aria-checked")).toBe("false");
|
||||
flushSync(() => page.connect().click());
|
||||
|
||||
@@ -44,7 +44,7 @@ function McpConnectRequest({ id }: { id: string }) {
|
||||
</div> : <fieldset className="space-y-2" disabled={consent.isPending}>
|
||||
<legend className="mb-2 text-sm font-medium">Organization</legend>
|
||||
{data.companies.map((item) => <label key={item.id} className="flex items-center gap-3 rounded-md border border-border p-3 text-sm">
|
||||
<input type="radio" name="company" aria-label={item.name} value={item.id} checked={companyId === item.id} onChange={() => { setCompanyId(item.id); setWriteEnabled(true); }} />
|
||||
<input type="radio" name="company" aria-label={item.name} value={item.id} checked={companyId === item.id} onChange={() => setCompanyId(item.id)} />
|
||||
<CompanyPatternIcon companyName={item.name} logoUrl={item.logoUrl} className="size-12 shrink-0 rounded-lg" />
|
||||
<span className="min-w-0 break-words font-medium">{item.name}</span>
|
||||
</label>)}
|
||||
|
||||
@@ -27,10 +27,14 @@ export const AllowDelegation: Story = { play: async context => {
|
||||
export const SwitchingOrganizationsResetsConsent: Story = { play: async context => {
|
||||
await AllowDelegation.play!(context);
|
||||
const c = within(context.canvasElement);
|
||||
await userEvent.click(c.getByRole("checkbox"));
|
||||
await userEvent.click(c.getByRole("radio", { name: "Design Partners" }));
|
||||
await expect(c.getByRole("checkbox")).not.toBeChecked();
|
||||
await expect(c.getByRole("checkbox")).toBeDisabled();
|
||||
await expect(c.getByText("Your role in this organization is read-only.")).toBeVisible();
|
||||
await userEvent.click(c.getByRole("radio", { name: "Acme Research" }));
|
||||
await expect(c.getByRole("checkbox")).toBeEnabled();
|
||||
await expect(c.getByRole("checkbox")).not.toBeChecked();
|
||||
} };
|
||||
export const ReadOnlyRequest: Story = { parameters: { fixture: { request: { clientName: "Claude", redirectOrigin: "https://claude.ai", requestedWrite: false, offlineAccess: false } } } };
|
||||
export const SignInRequired: Story = { parameters: { fixture: { request: { requiresSignIn: true, companies: [] } } } };
|
||||
|
||||
Reference in new issue
Block a user