-
Notifications
You must be signed in to change notification settings - Fork 12.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
01459f1
commit 5a982c1
Showing
3 changed files
with
355 additions
and
0 deletions.
There are no files selected for viewing
276 changes: 276 additions & 0 deletions
276
packages/editor-ui/src/components/CredentialPicker/CredentialPicker.test.constants.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,276 @@ | ||
import type { ICredentialMap, ICredentialTypeMap } from '@/Interface'; | ||
|
||
export const TEST_CREDENTIALS: ICredentialMap = { | ||
// OpenAI credential in personal | ||
1: { | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
id: '1', | ||
name: 'OpenAi account', | ||
data: 'test123', | ||
type: 'openAiApi', | ||
isManaged: false, | ||
homeProject: { | ||
id: '1', | ||
type: 'personal', | ||
name: 'Kobi Dog <[email protected]>', | ||
icon: null, | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
}, | ||
sharedWithProjects: [ | ||
{ | ||
id: '2', | ||
type: 'team', | ||
name: 'Test Project', | ||
icon: { type: 'icon', value: 'exchange-alt' }, | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
}, | ||
], | ||
scopes: [ | ||
'credential:create', | ||
'credential:delete', | ||
'credential:list', | ||
'credential:move', | ||
'credential:read', | ||
'credential:share', | ||
'credential:update', | ||
], | ||
}, | ||
// Supabase credential in another project | ||
2: { | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
id: '2', | ||
name: 'Supabase account', | ||
data: 'test123', | ||
type: 'supabaseApi', | ||
isManaged: false, | ||
homeProject: { | ||
id: '2', | ||
type: 'team', | ||
name: 'Test Project', | ||
icon: { type: 'icon', value: 'exchange-alt' }, | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
}, | ||
sharedWithProjects: [], | ||
scopes: [ | ||
'credential:create', | ||
'credential:delete', | ||
'credential:list', | ||
'credential:move', | ||
'credential:read', | ||
'credential:share', | ||
'credential:update', | ||
], | ||
}, | ||
// Slack account in personal | ||
3: { | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
id: '3', | ||
name: 'Slack account', | ||
data: 'test123', | ||
type: 'slackOAuth2Api', | ||
isManaged: false, | ||
homeProject: { | ||
id: '1', | ||
type: 'personal', | ||
name: 'Kobi Dog <[email protected]>', | ||
icon: null, | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
}, | ||
sharedWithProjects: [], | ||
scopes: [ | ||
'credential:create', | ||
'credential:delete', | ||
'credential:list', | ||
'credential:move', | ||
'credential:read', | ||
'credential:share', | ||
'credential:update', | ||
], | ||
}, | ||
// OpenAI credential in another project | ||
4: { | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
id: '4', | ||
name: '[PROJECT] OpenAI Account', | ||
data: 'test123', | ||
type: 'openAiApi', | ||
isManaged: false, | ||
homeProject: { | ||
id: '2', | ||
type: 'team', | ||
name: 'Test Project', | ||
icon: { type: 'icon', value: 'exchange-alt' }, | ||
createdAt: new Date().toISOString(), | ||
updatedAt: new Date().toISOString(), | ||
}, | ||
sharedWithProjects: [], | ||
scopes: [ | ||
'credential:create', | ||
'credential:delete', | ||
'credential:list', | ||
'credential:move', | ||
'credential:read', | ||
'credential:share', | ||
'credential:update', | ||
], | ||
}, | ||
}; | ||
|
||
export const TEST_CREDENTIAL_TYPES: ICredentialTypeMap = { | ||
openAiApi: { | ||
name: 'openAiApi', | ||
displayName: 'OpenAi', | ||
documentationUrl: 'openAi', | ||
properties: [ | ||
{ | ||
displayName: 'API Key', | ||
name: 'apiKey', | ||
type: 'string', | ||
typeOptions: { | ||
password: true, | ||
}, | ||
required: true, | ||
default: '', | ||
}, | ||
{ | ||
displayName: 'Base URL', | ||
name: 'url', | ||
type: 'string', | ||
default: 'https://api.openai.com/v1', | ||
description: 'Override the base URL for the API', | ||
}, | ||
], | ||
authenticate: { | ||
type: 'generic', | ||
properties: { | ||
headers: { | ||
Authorization: '=Bearer {{$credentials.apiKey}}', | ||
}, | ||
}, | ||
}, | ||
test: { | ||
request: { | ||
baseURL: '={{$credentials?.url}}', | ||
url: '/models', | ||
}, | ||
}, | ||
iconUrl: { | ||
light: 'icons/n8n-nodes-base/dist/nodes/OpenAi/openai.svg', | ||
dark: 'icons/n8n-nodes-base/dist/nodes/OpenAi/openai.dark.svg', | ||
}, | ||
supportedNodes: [ | ||
'n8n-nodes-base.openAi', | ||
'@n8n/n8n-nodes-langchain.embeddingsOpenAi', | ||
'@n8n/n8n-nodes-langchain.lmChatOpenAi', | ||
'@n8n/n8n-nodes-langchain.lmOpenAi', | ||
], | ||
}, | ||
supabaseApi: { | ||
name: 'supabaseApi', | ||
displayName: 'Supabase API', | ||
documentationUrl: 'supabase', | ||
properties: [ | ||
{ | ||
displayName: 'Host', | ||
name: 'host', | ||
type: 'string', | ||
placeholder: 'https://your_account.supabase.co', | ||
default: '', | ||
}, | ||
{ | ||
displayName: 'Service Role Secret', | ||
name: 'serviceRole', | ||
type: 'string', | ||
default: '', | ||
typeOptions: { | ||
password: true, | ||
}, | ||
}, | ||
], | ||
authenticate: { | ||
type: 'generic', | ||
properties: { | ||
headers: { | ||
apikey: '={{$credentials.serviceRole}}', | ||
Authorization: '=Bearer {{$credentials.serviceRole}}', | ||
}, | ||
}, | ||
}, | ||
test: { | ||
request: { | ||
baseURL: '={{$credentials.host}}/rest/v1', | ||
headers: { | ||
Prefer: 'return=representation', | ||
}, | ||
url: '/', | ||
}, | ||
}, | ||
iconUrl: 'icons/n8n-nodes-base/dist/nodes/Supabase/supabase.svg', | ||
supportedNodes: ['n8n-nodes-base.supabase'], | ||
}, | ||
slackOAuth2Api: { | ||
name: 'slackOAuth2Api', | ||
extends: ['oAuth2Api'], | ||
displayName: 'Slack OAuth2 API', | ||
documentationUrl: 'slack', | ||
properties: [ | ||
{ | ||
displayName: 'Grant Type', | ||
name: 'grantType', | ||
type: 'hidden', | ||
default: 'authorizationCode', | ||
}, | ||
{ | ||
displayName: 'Authorization URL', | ||
name: 'authUrl', | ||
type: 'hidden', | ||
default: 'https://slack.com/oauth/v2/authorize', | ||
}, | ||
{ | ||
displayName: 'Access Token URL', | ||
name: 'accessTokenUrl', | ||
type: 'hidden', | ||
default: 'https://slack.com/api/oauth.v2.access', | ||
}, | ||
{ | ||
displayName: 'Scope', | ||
name: 'scope', | ||
type: 'hidden', | ||
default: 'chat:write', | ||
}, | ||
{ | ||
displayName: 'Auth URI Query Parameters', | ||
name: 'authQueryParameters', | ||
type: 'hidden', | ||
default: | ||
'user_scope=channels:read channels:write chat:write files:read files:write groups:read im:read mpim:read reactions:read reactions:write stars:read stars:write usergroups:write usergroups:read users.profile:read users.profile:write users:read', | ||
}, | ||
{ | ||
displayName: 'Authentication', | ||
name: 'authentication', | ||
type: 'hidden', | ||
default: 'body', | ||
}, | ||
{ | ||
displayName: | ||
'If you get an Invalid Scopes error, make sure you add the correct one <a target="_blank" href="https://docs.n8n.io/integrations/builtin/credentials/slack/#using-oauth">here</a> to your Slack integration', | ||
name: 'notice', | ||
type: 'notice', | ||
default: '', | ||
}, | ||
], | ||
iconUrl: 'icons/n8n-nodes-base/dist/nodes/Slack/slack.svg', | ||
supportedNodes: ['n8n-nodes-base.slack'], | ||
}, | ||
}; | ||
|
||
export const PERSONAL_OPENAI_CREDENTIAL = TEST_CREDENTIALS[1]; | ||
export const PROJECT_OPENAI_CREDENTIAL = TEST_CREDENTIALS[4]; |
78 changes: 78 additions & 0 deletions
78
packages/editor-ui/src/components/CredentialPicker/CredentialPicker.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { createComponentRenderer } from '@/__tests__/render'; | ||
import { mockedStore } from '@/__tests__/utils'; | ||
import { useCredentialsStore } from '@/stores/credentials.store'; | ||
import { createTestingPinia } from '@pinia/testing'; | ||
import CredentialPicker from './CredentialPicker.vue'; | ||
import { | ||
PERSONAL_OPENAI_CREDENTIAL, | ||
PROJECT_OPENAI_CREDENTIAL, | ||
TEST_CREDENTIAL_TYPES, | ||
TEST_CREDENTIALS, | ||
} from './CredentialPicker.test.constants'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { screen } from '@testing-library/vue'; | ||
|
||
vi.mock('vue-router', () => { | ||
const push = vi.fn(); | ||
const resolve = vi.fn().mockReturnValue({ href: 'https://test.com' }); | ||
return { | ||
useRouter: () => ({ | ||
push, | ||
resolve, | ||
}), | ||
useRoute: () => ({}), | ||
RouterLink: vi.fn(), | ||
}; | ||
}); | ||
|
||
let credentialsStore: ReturnType<typeof mockedStore<typeof useCredentialsStore>>; | ||
|
||
const renderComponent = createComponentRenderer(CredentialPicker); | ||
|
||
describe('CredentialPicker', () => { | ||
beforeEach(() => { | ||
createTestingPinia(); | ||
credentialsStore = mockedStore(useCredentialsStore); | ||
credentialsStore.state.credentials = TEST_CREDENTIALS; | ||
credentialsStore.state.credentialTypes = TEST_CREDENTIAL_TYPES; | ||
}); | ||
|
||
it('should render', () => { | ||
expect(() => | ||
renderComponent({ | ||
props: { | ||
appName: 'OpenAI', | ||
credentialType: 'openAiApi', | ||
selectedCredentialId: null, | ||
}, | ||
}), | ||
).not.toThrowError(); | ||
}); | ||
|
||
it('should only render personal credentials of the specified type', async () => { | ||
const TEST_APP_NAME = 'OpenAI'; | ||
const TEST_CREDENTIAL_TYPE = 'openAiApi'; | ||
const { getByTestId } = renderComponent({ | ||
props: { | ||
appName: TEST_APP_NAME, | ||
credentialType: TEST_CREDENTIAL_TYPE, | ||
selectedCredentialId: null, | ||
}, | ||
}); | ||
expect(getByTestId('credential-dropdown')).toBeInTheDocument(); | ||
expect(getByTestId('credential-dropdown')).toHaveAttribute( | ||
'credential-type', | ||
TEST_CREDENTIAL_TYPE, | ||
); | ||
// Open the dropdown | ||
await userEvent.click(getByTestId('credential-dropdown')); | ||
// Personal openAI credential should be in the dropdown | ||
expect( | ||
screen.getByTestId(`node-credentials-select-item-${PERSONAL_OPENAI_CREDENTIAL.id}`), | ||
).toBeInTheDocument(); | ||
// OpenAI credential that belong to other project should not be in the dropdown | ||
expect( | ||
screen.queryByTestId(`node-credentials-select-item-${PROJECT_OPENAI_CREDENTIAL.id}`), | ||
).not.toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters