Skip to content

Implement organization switching UI with e2e coverage #46

Description

@rowan-stein

User Request

Implement the organization switching feature in chat-app as described in the product spec (agynio/product/product/chat/chat.md). The backend now supports organization_id on CreateChat and GetChats (merged in agynio/chat#21). This includes the org switcher UI, no-organizations gate, org context state management, and comprehensive e2e tests without mocks.

Specification

Overview

Three areas of work:

  1. API layer — Add organizationId to chat types/hooks to match the updated backend proto
  2. UI & state — Organization context provider, user menu org switcher, no-orgs screen
  3. E2E tests — Update existing tests + add new tests for org switching behavior

1. API Layer Changes

src/api/types/chat.ts

Add organizationId to:

  • Chat type — organizationId: string (returned by backend)
  • CreateChatRequestorganizationId: string (required by backend)
  • GetChatsRequestorganizationId: string (required by backend)

src/api/modules/chat.ts

Update normalizeChat and request serialization to handle organizationId field (snake_case ↔ camelCase).

src/api/hooks/chat.ts

  • useChats() → accepts organizationId parameter, includes it in query key and request payload. Disabled when organizationId is undefined.
  • useCreateChat() → passes organizationId in the mutation request.

2. Organization Context Provider

Create src/organization/ (following the src/user/ pattern):

  • OrganizationContext + OrganizationProvider + useOrganization hook
  • On mount: fetches listAccessibleOrganizations
  • State: { organizations, selectedOrganizationId, selectOrganization, isLoading }
  • selectedOrganizationId defaults to first org; persisted to localStorage for session continuity
  • selectOrganization(id) updates state and invalidates org-scoped queries (chats, agents)
  • Place in provider hierarchy: inside UserProvider, outside App (in src/main.tsx)

3. User Menu — Organization Switcher

In the UserMenu component (currently in ChatsScreen.tsx):

Replace the current menu content with:

  1. Organization switcher section — list all orgs, highlight current, click to switch
    • Use DropdownMenuRadioGroup + DropdownMenuRadioItem (existing pattern from status toggle in ChatDetailHeader)
    • Current org is the selected radio item
  2. Separator
  3. Sign out button (existing, OIDC only)

Remove the disabled "Account" menu item (not in the product spec).

Behavior on org switch:

  • Conversation list reloads for new org
  • Selected conversation is cleared (navigate to /chats)
  • Agent list reloads

4. No Organizations Screen

When organizations.length === 0:

  • Replace the entire chat interface (both list and detail panels) with an onboarding screen
  • Content: inform user they need to either get an invite or create a new organization
  • This is a hard gate — no chat functionality until they belong to an org
  • Add data-testid="no-organizations-screen" for e2e testing

5. Chats Page Changes (src/pages/Chats.tsx)

  • Consume useOrganization() context instead of ad-hoc useAccessibleOrganizations()
  • Pass organizationId to useChats() and useCreateChat()
  • On org change (via useEffect on selectedOrganizationId): clear selectedChatId, navigate to /chats
  • Guard: if no orgs, render NoOrganizationsScreen instead of ChatsScreen

6. E2E Test Changes

Update existing helpers (test/e2e/chat-api.ts)

  • createChat(page, organizationId, participantId?) — add required organizationId parameter

Update existing tests

All tests that call createChat must create an organization first and pass it:

  • chats-list.spec.ts
  • chat-detail.spec.ts
  • chat-exchange.spec.ts
  • chat-with-agent.spec.ts (already creates org for agent — reuse for chat)

New e2e tests (test/e2e/organization-switching.spec.ts)

Tests must run against real backend (no mocks):

  1. Org switcher displays organizations — Sign in, verify the user menu shows available organizations
  2. Org switcher highlights current org — Verify the currently selected org is visually indicated
  3. Switching orgs reloads chat list — Create chats in org A and org B via API, switch orgs via UI, verify the chat list changes
  4. Switching orgs clears selected conversation — Select a chat in org A, switch to org B, verify no chat is selected
  5. No-organizations screen — User with zero orgs sees the onboarding screen instead of chat interface (use a fresh user email that has no orgs)

Data-testid Attributes

Add these for e2e targeting:

  • data-testid="user-menu-trigger" — user menu button
  • data-testid="org-switcher" — org radio group container
  • data-testid="org-item-{orgId}" — individual org radio item
  • data-testid="no-organizations-screen" — no-orgs onboarding screen
  • data-testid="current-org-name" — displays current org name (for assertions)

Reference Patterns

  • Status toggle dropdown in ChatDetailHeader — shows how DropdownMenuRadioGroup is used
  • src/user/ — pattern for context provider structure
  • test/e2e/chat-with-agent.spec.ts — shows createOrganization + createAgent flow

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions