mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-04 18:49:20 +02:00
fix(editor): Show switch-to-static warning after connecting a private credential (#31712)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f723f54879
commit
f1d87fddb2
|
|
@ -13,6 +13,7 @@ import { useWorkflowsStore } from '@/app/stores/workflows.store';
|
|||
import { useNodeTypesStore } from '@/app/stores/nodeTypes.store';
|
||||
import type { ICredentialsResponse } from '../../credentials.types';
|
||||
import { within, waitFor } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import type { ICredentialType, INode, INodeTypeDescription } from 'n8n-workflow';
|
||||
|
||||
vi.mock('vue-router', async () => ({
|
||||
|
|
@ -32,6 +33,17 @@ vi.mock('@/app/composables/useToast', () => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
const { confirmMock } = vi.hoisted(() => ({ confirmMock: vi.fn() }));
|
||||
|
||||
vi.mock('@/app/composables/useMessage', () => ({
|
||||
useMessage: () => ({ confirm: confirmMock }),
|
||||
}));
|
||||
|
||||
vi.mock('@/features/resolvers/composables/useDynamicCredentials', async () => {
|
||||
const { ref } = await vi.importActual<typeof import('vue')>('vue');
|
||||
return { useDynamicCredentials: () => ({ isEnabled: ref(true) }) };
|
||||
});
|
||||
|
||||
const oAuth2Api: ICredentialType = {
|
||||
name: 'oAuth2Api',
|
||||
displayName: 'OAuth2 API',
|
||||
|
|
@ -946,5 +958,60 @@ describe('CredentialEdit', () => {
|
|||
await retry(() => expect(credentialsStore.getCredentialData).toHaveBeenCalled());
|
||||
await retry(() => expect(queryByTestId('oauth-not-connected-banner')).not.toBeVisible());
|
||||
});
|
||||
|
||||
describe('switching a connected private credential to static', () => {
|
||||
test('shows the confirmation modal when the current user just connected, even if the server count is stale', async () => {
|
||||
confirmMock.mockResolvedValue('confirm');
|
||||
const pinia = createPiniaForBannerTest();
|
||||
// connectedByMe reflects the in-session connection; connectedUserCount is the
|
||||
// stale server value (0) that does not yet include the current user.
|
||||
const credentialsStore = setupOAuthCredential({
|
||||
isResolvable: true,
|
||||
connectedByMe: true,
|
||||
connectedUserCount: 0,
|
||||
});
|
||||
|
||||
const { getByRole } = renderComponent({
|
||||
props: {
|
||||
activeId: 'cred-banner',
|
||||
modalName: CREDENTIAL_EDIT_MODAL_KEY,
|
||||
mode: 'edit',
|
||||
},
|
||||
pinia,
|
||||
});
|
||||
|
||||
await retry(() => expect(credentialsStore.getCredentialData).toHaveBeenCalled());
|
||||
|
||||
await userEvent.click(getByRole('switch'));
|
||||
|
||||
await retry(() => expect(confirmMock).toHaveBeenCalled());
|
||||
expect(confirmMock.mock.calls[0][0]).toContain('1 user(s)');
|
||||
});
|
||||
|
||||
test('does not show the confirmation modal when no users are connected', async () => {
|
||||
confirmMock.mockResolvedValue('confirm');
|
||||
const pinia = createPiniaForBannerTest();
|
||||
const credentialsStore = setupOAuthCredential({
|
||||
isResolvable: true,
|
||||
connectedByMe: false,
|
||||
connectedUserCount: 0,
|
||||
});
|
||||
|
||||
const { getByRole } = renderComponent({
|
||||
props: {
|
||||
activeId: 'cred-banner',
|
||||
modalName: CREDENTIAL_EDIT_MODAL_KEY,
|
||||
mode: 'edit',
|
||||
},
|
||||
pinia,
|
||||
});
|
||||
|
||||
await retry(() => expect(credentialsStore.getCredentialData).toHaveBeenCalled());
|
||||
|
||||
await userEvent.click(getByRole('switch'));
|
||||
|
||||
expect(confirmMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -785,8 +785,12 @@ async function onResolvableChange(value: boolean) {
|
|||
return;
|
||||
}
|
||||
} else if (isTogglingToStatic) {
|
||||
// Private → Static: warn only when there are connected users to disconnect
|
||||
const connectedUserCount = currentCredential.value?.connectedUserCount ?? 0;
|
||||
// Private → Static: warn only when there are connected users to disconnect.
|
||||
// `connectedUserCount` reflects the server state at modal-open and isn't
|
||||
// refreshed when the current user connects within the same session, so fold
|
||||
// in `connectedByMe` to make sure the warning still appears in that case.
|
||||
const serverConnectedCount = currentCredential.value?.connectedUserCount ?? 0;
|
||||
const connectedUserCount = Math.max(serverConnectedCount, connectedByMe.value ? 1 : 0);
|
||||
if (connectedUserCount > 0) {
|
||||
const confirmAction = await confirmModal('switchToStatic', {
|
||||
count: String(connectedUserCount),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user