diff --git a/app/src/components/composio/ComposioConnectModal.test.tsx b/app/src/components/composio/ComposioConnectModal.test.tsx new file mode 100644 index 0000000000..969dc84728 --- /dev/null +++ b/app/src/components/composio/ComposioConnectModal.test.tsx @@ -0,0 +1,100 @@ +import { render, screen } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; + +import { type ComposioConnection } from '../../lib/composio/types'; +import ComposioConnectModal from './ComposioConnectModal'; +import { composioToolkitMeta } from './toolkitMeta'; + +vi.mock('../../lib/composio/composioApi', () => ({ + authorize: vi.fn(), + deleteConnection: vi.fn(), + getUserScopes: vi.fn(() => Promise.resolve({ read: true, write: true, admin: false })), + listConnections: vi.fn(), + setUserScopes: vi.fn(), +})); + +vi.mock('../../utils/openUrl', () => ({ openUrl: vi.fn() })); + +// Mock TriggerToggles because it does its own API calls +vi.mock('./TriggerToggles', () => ({ default: () =>
})); + +const mockToolkit = composioToolkitMeta('gmail'); + +describe('', () => { + it('hides raw connection ID and "id:" label in connected phase', () => { + const connection: ComposioConnection = { id: 'ca_xyz', toolkit: 'gmail', status: 'ACTIVE' }; + + render( + {}} /> + ); + + // Should be in 'connected' phase because connection.status is 'ACTIVE' + expect(screen.getByText(/Gmail is connected/)).toBeInTheDocument(); + expect(screen.queryByText(/ca_xyz/)).not.toBeInTheDocument(); + expect(screen.queryByText(/id:/)).not.toBeInTheDocument(); + }); + + it('renders accountEmail when provided', () => { + const connection: ComposioConnection = { + id: 'ca_xyz', + toolkit: 'gmail', + status: 'ACTIVE', + accountEmail: 'foo@bar.com', + }; + + render( + {}} /> + ); + + expect(screen.getByText('(foo@bar.com)')).toBeInTheDocument(); + }); + + it('renders workspace when accountEmail is missing', () => { + const connection: ComposioConnection = { + id: 'ca_xyz', + toolkit: 'gmail', + status: 'ACTIVE', + workspace: 'Acme', + }; + + render( + {}} /> + ); + + expect(screen.getByText('(Acme)')).toBeInTheDocument(); + }); + + it('renders username when email and workspace are missing', () => { + const connection: ComposioConnection = { + id: 'ca_xyz', + toolkit: 'gmail', + status: 'ACTIVE', + username: 'oxox', + }; + + render( + {}} /> + ); + + expect(screen.getByText('(oxox)')).toBeInTheDocument(); + }); + + it('prioritizes accountEmail over workspace and username', () => { + const connection: ComposioConnection = { + id: 'ca_xyz', + toolkit: 'gmail', + status: 'ACTIVE', + accountEmail: 'foo@bar.com', + workspace: 'Acme', + username: 'oxox', + }; + + render( + {}} /> + ); + + expect(screen.getByText('(foo@bar.com)')).toBeInTheDocument(); + expect(screen.queryByText('(Acme)')).not.toBeInTheDocument(); + expect(screen.queryByText('(oxox)')).not.toBeInTheDocument(); + }); +}); diff --git a/app/src/components/composio/ComposioConnectModal.tsx b/app/src/components/composio/ComposioConnectModal.tsx index 0c49201b8f..846c5072b5 100644 --- a/app/src/components/composio/ComposioConnectModal.tsx +++ b/app/src/components/composio/ComposioConnectModal.tsx @@ -32,6 +32,14 @@ import { openUrl } from '../../utils/openUrl'; import type { ComposioToolkitMeta } from './toolkitMeta'; import TriggerToggles from './TriggerToggles'; +function deriveConnectionLabel(c: ComposioConnection): string | null { + for (const value of [c.accountEmail, c.workspace, c.username]) { + const normalized = value?.trim(); + if (normalized) return normalized; + } + return null; +} + type Phase = 'idle' | 'authorizing' | 'waiting' | 'connected' | 'disconnecting' | 'error'; interface ComposioConnectModalProps { @@ -392,9 +400,9 @@ export default function ComposioConnectModal({
{toolkit.name} is connected.   - {activeConnection && ( + {activeConnection && deriveConnectionLabel(activeConnection) && ( - (id: {activeConnection.id}) + ({deriveConnectionLabel(activeConnection)}) )}
diff --git a/app/src/lib/composio/types.ts b/app/src/lib/composio/types.ts index 30aa67fcde..f614a8634a 100644 --- a/app/src/lib/composio/types.ts +++ b/app/src/lib/composio/types.ts @@ -16,6 +16,11 @@ export interface ComposioConnection { status: string; /** ISO timestamp (backend passthrough). */ createdAt?: string; + + /** Optional friendly identity fields populated by later backend versions. */ + accountEmail?: string; + workspace?: string; + username?: string; } export interface ComposioConnectionsResponse {