diff --git a/frontend/src/upload/Upload.test.tsx b/frontend/src/upload/Upload.test.tsx index 37f866ce..50cd1b08 100644 --- a/frontend/src/upload/Upload.test.tsx +++ b/frontend/src/upload/Upload.test.tsx @@ -43,6 +43,25 @@ vi.mock('../connectors/useConnectorLauncher', () => ({ default: () => ({ launch, modals: null }), })); +// The file picker reports its default account and a pick as it mounts. +vi.mock('../components/FilePicker', async () => { + const { useEffect } = await import('react'); + return { + FilePicker: function Picker(props: { + onConnectionChange: (id: string | null) => void; + onSelectionChange: (files: string[], folders?: string[]) => void; + onFirstPickName: (name: string) => void; + }) { + useEffect(() => { + props.onConnectionChange('drive-1'); + props.onSelectionChange(['file-1'], []); + props.onFirstPickName('Handbook'); + }, []); + return null; + }, + }; +}); + import Upload from './Upload'; Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true }); @@ -265,6 +284,52 @@ describe('Upload source-type tiles', () => { connectorsState.connections = []; }); + it("sends the picker's account, not one cleared by the type change", async () => { + connectorsState.catalog = [ + { + key: 'google_drive', + icon: 'drive', + sync_ingestor: 'google_drive', + auth_kind: 'oauth', + available: true, + missing_settings: [], + }, + ]; + const sent: FormData[] = []; + class FakeXhr { + upload = { addEventListener() {} }; + addEventListener() {} + open() {} + setRequestHeader() {} + send(body: FormData) { + sent.push(body); + } + } + vi.stubGlobal('XMLHttpRequest', FakeXhr); + await act(async () => + root.render( + , + ), + ); + const train = Array.from(document.body.querySelectorAll('button')).find( + (b) => b.textContent === 'modals.uploadDoc.train', + )!; + await act(async () => train.click()); + expect(sent).toHaveLength(1); + expect(JSON.parse(String(sent[0].get('data'))).connection_id).toBe( + 'drive-1', + ); + vi.unstubAllGlobals(); + connectorsState.catalog = []; + }); + it('leaves the disabled Train button on the default variant', async () => { await render(); const crawler = tiles().find((tile) => diff --git a/frontend/src/upload/Upload.tsx b/frontend/src/upload/Upload.tsx index aadb7a55..0b533402 100644 --- a/frontend/src/upload/Upload.tsx +++ b/frontend/src/upload/Upload.tsx @@ -556,10 +556,6 @@ function Upload({ // user made in the account picker. const accountPicked = useRef(false); const firstKeyAccount = keyAccounts[0]?.id; - useEffect(() => { - accountPicked.current = false; - setConnectionId(null); - }, [ingestor.type]); useEffect(() => { if (selectedConnector?.auth_kind !== 'api_key' || accountPicked.current) return; @@ -1159,6 +1155,11 @@ function Upload({ })); }; const handleIngestorTypeChange = (type: IngestorType | null) => { + // The account resets with the type, here rather than in an effect: the + // new type's picker reports its default account as it mounts, and an + // effect would run after that and clear it. + accountPicked.current = false; + setConnectionId(null); if (type === null) { setIngestor({ type: null, @@ -1204,7 +1205,8 @@ function Upload({ count: accounts.length, formatted: formatCount(accounts.length), }); - return t('settings.connectors.status.connect'); + // A status, not a button: the tile itself starts the connection. + return t('modals.uploadDoc.tileNotConnected'); }; // With the catalog loaded, members only see connections they can use: