From abd7f75b8d07271e094ddc81bf556030f6e793ac Mon Sep 17 00:00:00 2001 From: Carl Taylor Date: Thu, 20 Aug 2026 16:43:51 +1000 Subject: [PATCH] fix(desktop): keep Messaging on active profile --- apps/desktop/src/app/messaging/index.test.tsx | 29 +++++++++++++++---- apps/desktop/src/app/messaging/index.tsx | 7 +++-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/apps/desktop/src/app/messaging/index.test.tsx b/apps/desktop/src/app/messaging/index.test.tsx index 72d9c10044..75bb9701e6 100644 --- a/apps/desktop/src/app/messaging/index.test.tsx +++ b/apps/desktop/src/app/messaging/index.test.tsx @@ -13,13 +13,16 @@ const revokePairing = vi.fn() const openExternalLink = vi.fn() vi.mock('@/hermes', () => ({ - approvePairing: (platformId: string, requestId: string) => approvePairing(platformId, requestId), - getMessagingPlatforms: () => getMessagingPlatforms(), - getPairing: () => getPairing(), + approvePairing: (platformId: string, requestId: string, profile?: null | string) => + approvePairing(platformId, requestId, profile), + getMessagingPlatforms: (profile?: null | string) => getMessagingPlatforms(profile), + getPairing: (profile?: null | string) => getPairing(profile), getProfiles: vi.fn(async () => ({ profiles: [] })), - revokePairing: (platformId: string, userId: string) => revokePairing(platformId, userId), + revokePairing: (platformId: string, userId: string, profile?: null | string) => + revokePairing(platformId, userId, profile), setApiRequestProfile: vi.fn(), - updateMessagingPlatform: (id: string, body: unknown) => updateMessagingPlatform(id, body) + updateMessagingPlatform: (id: string, body: unknown, profile?: null | string) => + updateMessagingPlatform(id, body, profile) })) // Keep store/profile's side-effecting imports inert (pulled in via the shared @@ -85,6 +88,20 @@ async function renderMessaging() { return result! } +describe('MessagingView profile scope', () => { + it('follows the active profile instead of targeting primary when there is no override', async () => { + const { $settingsScopeOverride } = await import('@/store/settings-scope') + + $settingsScopeOverride.set(null) + getMessagingPlatforms.mockResolvedValue({ platforms: [platform()] }) + + await renderMessaging() + + await waitFor(() => expect(getMessagingPlatforms).toHaveBeenCalledWith(undefined)) + expect(getPairing).toHaveBeenCalledWith(undefined) + }) +}) + describe('MessagingView setup-guide link', () => { it('hides the setup-guide button for a plugin platform with no docs URL', async () => { // Teams (and other plugin platforms) ship an empty docs_url. Rendering an @@ -138,7 +155,7 @@ describe('MessagingView pairing', () => { fireEvent.click(approve) }) - await waitFor(() => expect(approvePairing).toHaveBeenCalledWith('teams', 'a1b2c3d4e5f60718')) + await waitFor(() => expect(approvePairing).toHaveBeenCalledWith('teams', 'a1b2c3d4e5f60718', undefined)) }) it('restores the pending row when approval fails', async () => { diff --git a/apps/desktop/src/app/messaging/index.tsx b/apps/desktop/src/app/messaging/index.tsx index 579305dd3b..0a1cc8e7ff 100644 --- a/apps/desktop/src/app/messaging/index.tsx +++ b/apps/desktop/src/app/messaging/index.tsx @@ -128,9 +128,10 @@ function fieldCopy(field: MessagingEnvVarInfo, m: Translations['messaging']) { export function MessagingView({ setStatusbarItemGroup: _setStatusbarItemGroup, ...props }: MessagingViewProps) { const { t } = useI18n() const m = t.messaging - // Shared settings "Applies to" scope: configure another profile's gateway - // platforms/pairing without switching the whole app (null → active profile). - const scopeProfile = useStore($settingsScopeOverride) + // Shared settings "Applies to" scope. At this layer `null` means "follow + // the active profile", while the API helpers use `undefined` for that + // contract; passing null would deliberately target the primary profile. + const scopeProfile = useStore($settingsScopeOverride) ?? undefined // Both save/toggle toasts offer the same one-click restart. const restartGatewayAction = { label: t.commandCenter.restartGateway, onClick: () => void runGatewayRestart() } const [platforms, setPlatforms] = useState(null)