From fa664010f169a643eb2d46134cab017f24f7f326 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Fri, 26 Sep 2025 16:34:36 +0200 Subject: [PATCH] fix(editor): Fix empty credential translation (#20019) --- .../src/components/CredentialConfig.test.ts | 105 ++++++++++++++++++ .../CredentialEdit/CredentialConfig.vue | 2 + 2 files changed, 107 insertions(+) diff --git a/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts b/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts index 0e8d8fcf91f..6cd692ff5d3 100644 --- a/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts +++ b/packages/frontend/editor-ui/src/components/CredentialConfig.test.ts @@ -5,6 +5,17 @@ import { createTestingPinia } from '@pinia/testing'; import type { RenderOptions } from '@/__tests__/render'; import { createComponentRenderer } from '@/__tests__/render'; import { STORES } from '@n8n/stores'; +import { vi } from 'vitest'; +import { useCredentialsStore } from '@/stores/credentials.store'; +import { addCredentialTranslation } from '@n8n/i18n'; + +vi.mock('@n8n/i18n', async () => { + const actual = await vi.importActual('@n8n/i18n'); + return { + ...actual, + addCredentialTranslation: vi.fn(), + }; +}); const defaultRenderOptions: RenderOptions = { pinia: createTestingPinia({ @@ -53,4 +64,98 @@ describe('CredentialConfig', () => { screen.queryByText('This is a managed credential and cannot be edited.'), ).not.toBeInTheDocument(); }); + + it('should not call addCredentialTranslation when getCredentialTranslation returns null', async () => { + const mockCredentialType = { + name: 'testCredential', + displayName: 'Test Credential', + } as ICredentialType; + + const pinia = createTestingPinia({ + initialState: { + [STORES.SETTINGS]: { + settings: { + enterprise: { + sharing: false, + externalSecrets: false, + }, + }, + }, + [STORES.ROOT]: { + defaultLocale: 'de', // Non-English locale to trigger translation loading + }, + }, + stubActions: false, + }); + + // Mock the getCredentialTranslation method to return null + const credentialsStore = useCredentialsStore(); + credentialsStore.getCredentialTranslation = vi.fn().mockResolvedValue(null); + + // Clear any previous calls to addCredentialTranslation + vi.mocked(addCredentialTranslation).mockClear(); + + renderComponent( + { + props: { + credentialType: mockCredentialType, + }, + pinia, + }, + { merge: true }, + ); + + // Wait for the component to mount and onBeforeMount to complete + await new Promise((resolve) => setTimeout(resolve, 0)); + + // Verify that addCredentialTranslation was not called + expect(addCredentialTranslation).not.toHaveBeenCalled(); + }); + + it('should not call addCredentialTranslation when getCredentialTranslation returns undefined', async () => { + const mockCredentialType = { + name: 'testCredential', + displayName: 'Test Credential', + } as ICredentialType; + + const pinia = createTestingPinia({ + initialState: { + [STORES.SETTINGS]: { + settings: { + enterprise: { + sharing: false, + externalSecrets: false, + }, + }, + }, + [STORES.ROOT]: { + defaultLocale: 'de', // Non-English locale to trigger translation loading + }, + }, + stubActions: false, + }); + + // Mock the getCredentialTranslation method to return undefined + const credentialsStore = useCredentialsStore(); + credentialsStore.getCredentialTranslation = vi.fn().mockResolvedValue(undefined); + + // Clear any previous calls to addCredentialTranslation + vi.mocked(addCredentialTranslation).mockClear(); + + renderComponent( + { + props: { + credentialType: mockCredentialType, + }, + pinia, + }, + { merge: true }, + ); + + // Wait for the component to mount and onBeforeMount to complete + await new Promise((resolve) => setTimeout(resolve, 0)); + + // Verify that addCredentialTranslation was not called + expect(addCredentialTranslation).not.toHaveBeenCalled(); + }); }); diff --git a/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue b/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue index 62173129b86..2969c5ce041 100644 --- a/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue +++ b/packages/frontend/editor-ui/src/components/CredentialEdit/CredentialConfig.vue @@ -92,6 +92,8 @@ onBeforeMount(async () => { props.credentialType.name, ); + if (!credTranslation) return; + addCredentialTranslation( { [props.credentialType.name]: credTranslation }, rootStore.defaultLocale,