From b69ea3b244a9520d94c029883b7af2301189621e Mon Sep 17 00:00:00 2001 From: "n8n-cat-bot[bot]" Date: Wed, 14 Oct 2026 14:03:18 +0000 Subject: [PATCH 1/2] test(editor): Reproduce scopes notice click behavior (NODE-5622) --- .../components/ScopesNotice.test.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts diff --git a/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts b/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts new file mode 100644 index 00000000000..7598c7576f8 --- /dev/null +++ b/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts @@ -0,0 +1,58 @@ +import { createTestingPinia } from '@pinia/testing'; +import userEvent from '@testing-library/user-event'; + +import { createComponentRenderer } from '@/__tests__/render'; +import { useCredentialsStore } from '../credentials.store'; +import ScopesNotice from './ScopesNotice.vue'; + +const renderComponent = createComponentRenderer(ScopesNotice); + +describe('ScopesNotice', () => { + beforeEach(() => { + createTestingPinia(); + useCredentialsStore().state.credentialTypes = { + testOAuth2Api: { + name: 'testOAuth2Api', + displayName: 'Test OAuth2 API', + properties: [], + }, + }; + }); + + it('reveals the available scopes when clicking the scope count', async () => { + const { getByText, getByRole } = renderComponent({ + props: { + activeCredentialType: 'testOAuth2Api', + scopes: ['read:items', 'write:items'], + }, + }); + + expect(getByRole('region')).not.toHaveTextContent('read:items'); + expect(getByRole('region')).not.toHaveTextContent('write:items'); + + await userEvent.click(getByText('2 scopes')); + + expect(getByRole('region')).toHaveTextContent('read:items'); + expect(getByRole('region')).toHaveTextContent('write:items'); + expect(getByText('Show less')).toBeVisible(); + }); + + // NODE-5622: Users expect the "scopes available" control to reveal the scope list. + it('reveals the available scopes when clicking the available label', async () => { + const { getByText, getByRole } = renderComponent({ + props: { + activeCredentialType: 'testOAuth2Api', + scopes: ['read:items', 'write:items'], + }, + }); + + expect(getByRole('region')).not.toHaveTextContent('read:items'); + expect(getByRole('region')).not.toHaveTextContent('write:items'); + + await userEvent.click(getByText('available for Test credentials', { exact: false })); + + expect(getByRole('region')).toHaveTextContent('read:items'); + expect(getByRole('region')).toHaveTextContent('write:items'); + expect(getByText('Show less')).toBeVisible(); + }); +}); From 1abbf7a4d90105fb316c160b0b62ecaa168f5d33 Mon Sep 17 00:00:00 2001 From: "n8n-cat-bot[bot]" Date: Wed, 14 Oct 2026 14:19:29 +0000 Subject: [PATCH 2/2] fix(editor): Expand the scopes available link (NODE-5622) --- .../frontend/@n8n/i18n/src/locales/en.json | 4 +- .../components/ScopesNotice.test.ts | 37 ++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/frontend/@n8n/i18n/src/locales/en.json b/packages/frontend/@n8n/i18n/src/locales/en.json index 240a59e964a..3a2899c04e1 100644 --- a/packages/frontend/@n8n/i18n/src/locales/en.json +++ b/packages/frontend/@n8n/i18n/src/locales/en.json @@ -2512,8 +2512,8 @@ "nodeSettings.communityNodeTooltip": "This is a community node", "nodeSettings.retryOnFail.description": "If active, the node tries to execute again when it fails", "nodeSettings.retryOnFail.displayName": "Retry On Fail", - "nodeSettings.scopes.expandedNoticeWithScopes": "{count} scope available for {activeCredential} credentials
{scopes}
Show less | {count} scopes available for {activeCredential} credentials
{scopes}
Show less", - "nodeSettings.scopes.notice": "{count} scope available for {activeCredential} credentials | {count} scopes available for {activeCredential} credentials", + "nodeSettings.scopes.expandedNoticeWithScopes": "{count} scope available for {activeCredential} credentials
{scopes}
Show less | {count} scopes available for {activeCredential} credentials
{scopes}
Show less", + "nodeSettings.scopes.notice": "{count} scope available for {activeCredential} credentials | {count} scopes available for {activeCredential} credentials", "nodeSettings.theNodeIsNotValidAsItsTypeIsUnknown": "The node is not valid as its type ({nodeType}) is unknown", "nodeSettings.communityNodeDetails.title": "Node details", "nodeSettings.communityNodeUnknown.title": "Install this node to use it", diff --git a/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts b/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts index 7598c7576f8..32a23ade5ff 100644 --- a/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts +++ b/packages/frontend/editor-ui/src/features/credentials/components/ScopesNotice.test.ts @@ -7,7 +7,10 @@ import ScopesNotice from './ScopesNotice.vue'; const renderComponent = createComponentRenderer(ScopesNotice); -describe('ScopesNotice', () => { +describe.each([ + { scopeCount: '1 scope', scopes: ['read:items'] }, + { scopeCount: '2 scopes', scopes: ['read:items', 'write:items'] }, +])('ScopesNotice ($scopeCount)', ({ scopeCount, scopes }) => { beforeEach(() => { createTestingPinia(); useCredentialsStore().state.credentialTypes = { @@ -23,18 +26,26 @@ describe('ScopesNotice', () => { const { getByText, getByRole } = renderComponent({ props: { activeCredentialType: 'testOAuth2Api', - scopes: ['read:items', 'write:items'], + scopes, }, }); expect(getByRole('region')).not.toHaveTextContent('read:items'); expect(getByRole('region')).not.toHaveTextContent('write:items'); - await userEvent.click(getByText('2 scopes')); + await userEvent.click(getByText(scopeCount, { exact: false })); - expect(getByRole('region')).toHaveTextContent('read:items'); - expect(getByRole('region')).toHaveTextContent('write:items'); + for (const scope of scopes) { + expect(getByRole('region')).toHaveTextContent(scope); + } expect(getByText('Show less')).toBeVisible(); + + await userEvent.click(getByText('Show less')); + + for (const scope of scopes) { + expect(getByRole('region')).not.toHaveTextContent(scope); + } + expect(getByText(`${scopeCount} available`)).toBeVisible(); }); // NODE-5622: Users expect the "scopes available" control to reveal the scope list. @@ -42,17 +53,25 @@ describe('ScopesNotice', () => { const { getByText, getByRole } = renderComponent({ props: { activeCredentialType: 'testOAuth2Api', - scopes: ['read:items', 'write:items'], + scopes, }, }); expect(getByRole('region')).not.toHaveTextContent('read:items'); expect(getByRole('region')).not.toHaveTextContent('write:items'); - await userEvent.click(getByText('available for Test credentials', { exact: false })); + await userEvent.click(getByText(/available/)); - expect(getByRole('region')).toHaveTextContent('read:items'); - expect(getByRole('region')).toHaveTextContent('write:items'); + for (const scope of scopes) { + expect(getByRole('region')).toHaveTextContent(scope); + } expect(getByText('Show less')).toBeVisible(); + + await userEvent.click(getByText(/available/)); + + for (const scope of scopes) { + expect(getByRole('region')).not.toHaveTextContent(scope); + } + expect(getByText(`${scopeCount} available`)).toBeVisible(); }); });