fix(cli-status): refresh auth after terminal close
This commit is contained in:
parent
877a81439b
commit
46a525aea1
4 changed files with 140 additions and 26 deletions
|
|
@ -1759,9 +1759,6 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
setProviderTerminal(null);
|
||||
recheckAuthState();
|
||||
}}
|
||||
onExit={() => {
|
||||
recheckAuthState();
|
||||
}}
|
||||
autoCloseOnSuccessMs={3000}
|
||||
successMessage={
|
||||
providerTerminal.action === 'login'
|
||||
|
|
@ -2367,21 +2364,6 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
}
|
||||
})();
|
||||
}}
|
||||
onExit={() => {
|
||||
setIsVerifyingAuth(true);
|
||||
void (async () => {
|
||||
try {
|
||||
await invalidateCliStatus();
|
||||
if (multimodelEnabled) {
|
||||
await bootstrapCliStatus({ multimodelEnabled: true });
|
||||
} else {
|
||||
await fetchCliStatus();
|
||||
}
|
||||
} finally {
|
||||
setIsVerifyingAuth(false);
|
||||
}
|
||||
})();
|
||||
}}
|
||||
autoCloseOnSuccessMs={4000}
|
||||
successMessage={t('cliStatus.labels.loginComplete')}
|
||||
failureMessage={t('cliStatus.labels.loginFailed')}
|
||||
|
|
|
|||
|
|
@ -862,9 +862,6 @@ export const CliStatusSection = (): React.JSX.Element | null => {
|
|||
setProviderTerminal(null);
|
||||
recheckStatus();
|
||||
}}
|
||||
onExit={() => {
|
||||
recheckStatus();
|
||||
}}
|
||||
autoCloseOnSuccessMs={3000}
|
||||
successMessage={
|
||||
providerTerminal.action === 'login'
|
||||
|
|
|
|||
|
|
@ -180,10 +180,6 @@ export const ProvisioningProviderRuntimeSettingsDialog = ({
|
|||
onProviderRuntimeChanged?.(providerTerminal.providerId);
|
||||
refreshRuntimeAfterTerminal();
|
||||
}}
|
||||
onExit={() => {
|
||||
onProviderRuntimeChanged?.(providerTerminal.providerId);
|
||||
refreshRuntimeAfterTerminal();
|
||||
}}
|
||||
autoCloseOnSuccessMs={3000}
|
||||
successMessage={
|
||||
providerTerminal.action === 'login' ? 'Authentication updated' : 'Provider logged out'
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@ let providerRuntimeSettingsDialogProps: {
|
|||
open?: boolean;
|
||||
initialProviderId?: string;
|
||||
} | null = null;
|
||||
let terminalModalProps: {
|
||||
onClose?: () => void;
|
||||
onExit?: (exitCode: number) => void;
|
||||
} | null = null;
|
||||
const codexAccountHookState = {
|
||||
snapshot: null as CodexAccountSnapshotDto | null,
|
||||
loading: false,
|
||||
|
|
@ -160,7 +164,23 @@ vi.mock('@renderer/components/terminal/TerminalLogPanel', () => ({
|
|||
}));
|
||||
|
||||
vi.mock('@renderer/components/terminal/TerminalModal', () => ({
|
||||
TerminalModal: () => React.createElement('div', { 'data-testid': 'terminal-modal' }, 'terminal'),
|
||||
TerminalModal: (props: { onClose?: () => void; onExit?: (exitCode: number) => void }) => {
|
||||
terminalModalProps = props;
|
||||
return React.createElement(
|
||||
'div',
|
||||
{ 'data-testid': 'terminal-modal' },
|
||||
React.createElement(
|
||||
'button',
|
||||
{ 'data-testid': 'terminal-exit', onClick: () => props.onExit?.(0) },
|
||||
'exit'
|
||||
),
|
||||
React.createElement(
|
||||
'button',
|
||||
{ 'data-testid': 'terminal-close', onClick: () => props.onClose?.() },
|
||||
'close'
|
||||
)
|
||||
);
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('@renderer/store', () => {
|
||||
|
|
@ -345,6 +365,7 @@ describe('CLI status visibility during completed install state', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
providerRuntimeSettingsDialogProps = null;
|
||||
terminalModalProps = null;
|
||||
codexAccountHookState.snapshot = null;
|
||||
codexAccountHookState.loading = false;
|
||||
codexAccountHookState.rateLimitsLoading = false;
|
||||
|
|
@ -518,6 +539,50 @@ describe('CLI status visibility during completed install state', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('waits until the runtime login modal closes before refreshing auth status', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliStatus = createInstalledCliStatus({
|
||||
authLoggedIn: false,
|
||||
});
|
||||
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const root = createRoot(host);
|
||||
|
||||
await act(async () => {
|
||||
root.render(React.createElement(CliStatusBanner));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
const loginButton = Array.from(host.querySelectorAll('button')).find(
|
||||
(button) => button.textContent?.trim() === 'Login'
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
loginButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(host.querySelector('[data-testid="terminal-modal"]')).not.toBeNull();
|
||||
expect(terminalModalProps?.onExit).toBeUndefined();
|
||||
|
||||
storeState.invalidateCliStatus.mockClear();
|
||||
storeState.bootstrapCliStatus.mockClear();
|
||||
|
||||
await act(async () => {
|
||||
terminalModalProps?.onClose?.();
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(storeState.invalidateCliStatus).toHaveBeenCalledTimes(1);
|
||||
expect(storeState.bootstrapCliStatus).toHaveBeenCalledTimes(1);
|
||||
|
||||
await act(async () => {
|
||||
root.unmount();
|
||||
await flushLazyImports();
|
||||
});
|
||||
});
|
||||
|
||||
it('loads the installer terminal log only while installation is active', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliInstallerState = 'installing';
|
||||
|
|
@ -1427,6 +1492,80 @@ describe('CLI status visibility during completed install state', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('waits until the provider login modal closes before refreshing provider auth status', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliInstallerState = 'idle';
|
||||
storeState.cliStatus = createInstalledCliStatus({
|
||||
flavor: 'agent_teams_orchestrator',
|
||||
authLoggedIn: false,
|
||||
providers: [
|
||||
{
|
||||
providerId: 'anthropic',
|
||||
displayName: 'Anthropic',
|
||||
supported: true,
|
||||
authenticated: false,
|
||||
authMethod: null,
|
||||
verificationState: 'verified',
|
||||
statusMessage: 'Not connected',
|
||||
models: [],
|
||||
canLoginFromUi: true,
|
||||
capabilities: {
|
||||
teamLaunch: true,
|
||||
oneShot: true,
|
||||
},
|
||||
connection: {
|
||||
supportsOAuth: true,
|
||||
supportsApiKey: true,
|
||||
configurableAuthModes: ['auto', 'oauth', 'api_key'],
|
||||
configuredAuthMode: 'auto',
|
||||
apiKeyConfigured: false,
|
||||
apiKeySource: null,
|
||||
apiKeySourceLabel: null,
|
||||
},
|
||||
backend: null,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const root = createRoot(host);
|
||||
|
||||
await act(async () => {
|
||||
root.render(React.createElement(CliStatusBanner));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
const connectButton = Array.from(host.querySelectorAll('button')).find((button) =>
|
||||
button.textContent?.includes('Connect Anthropic')
|
||||
);
|
||||
expect(connectButton).not.toBeUndefined();
|
||||
|
||||
await act(async () => {
|
||||
connectButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(host.querySelector('[data-testid="terminal-modal"]')).not.toBeNull();
|
||||
expect(terminalModalProps?.onExit).toBeUndefined();
|
||||
|
||||
storeState.invalidateCliStatus.mockClear();
|
||||
storeState.bootstrapCliStatus.mockClear();
|
||||
|
||||
await act(async () => {
|
||||
terminalModalProps?.onClose?.();
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(storeState.invalidateCliStatus).toHaveBeenCalledTimes(1);
|
||||
expect(storeState.bootstrapCliStatus).toHaveBeenCalledTimes(1);
|
||||
|
||||
await act(async () => {
|
||||
root.unmount();
|
||||
await flushLazyImports();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows subscription limit placeholders while an Anthropic subscription provider is checking', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliInstallerState = 'idle';
|
||||
|
|
|
|||
Loading…
Reference in a new issue