From 301a59ef51aa4ed999510f97271e50b0c8650c69 Mon Sep 17 00:00:00 2001
From: arc53-machine <232052973+arc53-machine@users.noreply.github.com>
Date: Tue, 29 Sep 2026 11:38:27 +0100
Subject: [PATCH] Open Sync more for an MCP preset at choosing what to sync
The launcher passed only reconnect through for MCP presets, so Sync more
on a Linear account asked to sign in again instead of showing its teams.
---
.../connectors/useConnectorLauncher.test.tsx | 92 +++++++++++++++++++
.../src/connectors/useConnectorLauncher.tsx | 3 +-
2 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 frontend/src/connectors/useConnectorLauncher.test.tsx
diff --git a/frontend/src/connectors/useConnectorLauncher.test.tsx b/frontend/src/connectors/useConnectorLauncher.test.tsx
new file mode 100644
index 00000000..af4eee49
--- /dev/null
+++ b/frontend/src/connectors/useConnectorLauncher.test.tsx
@@ -0,0 +1,92 @@
+import { configureStore } from '@reduxjs/toolkit';
+import { act } from 'react';
+import { createRoot, type Root } from 'react-dom/client';
+import { Provider } from 'react-redux';
+import { MemoryRouter } from 'react-router-dom';
+
+// The wizard is tested on its own; here only what it is opened with matters.
+vi.mock('./ConnectWizard', () => ({
+ default: ({
+ mode,
+ connectionId,
+ }: {
+ mode: string;
+ connectionId?: string;
+ }) =>
{`${mode}:${connectionId ?? ''}`}
,
+}));
+vi.mock('../modals/MCPServerModal', () => ({ default: () => null }));
+
+import connectorsReducer from './connectorsSlice';
+import type { ConnectorDefinition } from './types';
+import useConnectorLauncher, {
+ type LaunchOptions,
+} from './useConnectorLauncher';
+
+Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });
+
+const LINEAR = {
+ key: 'mcp:linear',
+ name: 'Linear',
+ auth_kind: 'mcp_oauth',
+ mcp_url: 'https://mcp.linear.app/mcp',
+ sync_ingestor: 'linear',
+} as unknown as ConnectorDefinition;
+
+let launchRef: ((c: ConnectorDefinition, o?: LaunchOptions) => void) | null =
+ null;
+
+function Harness() {
+ const { launch, modals } = useConnectorLauncher();
+ launchRef = launch;
+ return <>{modals}>;
+}
+
+describe('useConnectorLauncher', () => {
+ let container: HTMLDivElement;
+ let root: Root;
+
+ beforeEach(async () => {
+ container = document.createElement('div');
+ document.body.appendChild(container);
+ root = createRoot(container);
+ const store = configureStore({
+ reducer: {
+ connectors: connectorsReducer,
+ preference: (state = { token: null }) => state,
+ },
+ });
+ await act(async () => {
+ root.render(
+
+
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(async () => {
+ await act(async () => root.unmount());
+ container.remove();
+ });
+
+ const wizard = () =>
+ container.querySelector('[data-testid="wizard"]')?.textContent;
+
+ it('opens an MCP preset that syncs straight at picking what to sync', async () => {
+ await act(async () =>
+ launchRef!(LINEAR, { mode: 'sync', connectionId: 'c1' }),
+ );
+ expect(wizard()).toBe('sync:c1');
+ });
+
+ it('opens an MCP preset at signing in to connect or reconnect', async () => {
+ await act(async () => launchRef!(LINEAR));
+ expect(wizard()).toBe('connect:');
+ await act(async () =>
+ launchRef!(LINEAR, { mode: 'reconnect', connectionId: 'c1' }),
+ );
+ expect(wizard()).toBe('reconnect:c1');
+ });
+});
diff --git a/frontend/src/connectors/useConnectorLauncher.tsx b/frontend/src/connectors/useConnectorLauncher.tsx
index b4b4c9e0..2028cdf0 100644
--- a/frontend/src/connectors/useConnectorLauncher.tsx
+++ b/frontend/src/connectors/useConnectorLauncher.tsx
@@ -62,7 +62,8 @@ export default function useConnectorLauncher({
setActive({
kind: 'wizard',
connector,
- mode: options.mode === 'reconnect' ? 'reconnect' : 'connect',
+ // Sync more from an account skips signing in, like any connector.
+ mode: options.mode ?? 'connect',
connectionId: options.connectionId,
mcpToolId:
typeof options.mcpServer?.id === 'string'