Skip to content

Commit

Permalink
feat(editor): Select credentials in template setup if theres only one (
Browse files Browse the repository at this point in the history
…#7879)

Automatically select credentials in the template credential setup if
there's only one available.

NOTE! This feature is still behind a feature flag. To test, set:

```js
localStorage.setItem('template-credentials-setup', 'true')
```


https://github.com/n8n-io/n8n/assets/10324676/edc1f586-214f-4c37-b7ec-dd1786433dc1
  • Loading branch information
tomi authored Nov 30, 2023
1 parent e0b7f89 commit fe3417a
Show file tree
Hide file tree
Showing 4 changed files with 466 additions and 0 deletions.
11 changes: 11 additions & 0 deletions packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,10 +817,20 @@ export interface ITemplatesWorkflow {
};
}

export interface ITemplatesWorkflowInfo {
nodeCount: number;
nodeTypes: {
[key: string]: {
count: number;
};
};
}

export interface ITemplatesWorkflowResponse extends ITemplatesWorkflow, IWorkflowTemplate {
description: string | null;
image: ITemplatesImage[];
categories: ITemplatesCategory[];
workflowInfo: ITemplatesWorkflowInfo;
}

/**
Expand Down Expand Up @@ -1010,6 +1020,7 @@ export interface IVersionNode {
}

export interface ITemplatesNode extends IVersionNode {
id: number;
categories?: ITemplatesCategory[];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { useTemplatesStore } from '@/stores/templates.store';
import type { IWorkflowTemplateNodeWithCredentials } from '@/utils/templates/templateTransforms';
import type { CredentialUsages } from '@/views/SetupWorkflowFromTemplateView/setupTemplate.store';
import {
getAppCredentials,
getAppsRequiringCredentials,
groupNodeCredentialsByName,
useSetupTemplateStore,
} from '@/views/SetupWorkflowFromTemplateView/setupTemplate.store';
import { setActivePinia } from 'pinia';
import * as testData from './setupTemplate.store.testData';
import { createTestingPinia } from '@pinia/testing';
import { useCredentialsStore } from '@/stores/credentials.store';

const objToMap = <T>(obj: Record<string, T>) => {
return new Map<string, T>(Object.entries(obj));
Expand Down Expand Up @@ -145,4 +151,111 @@ describe('SetupWorkflowFromTemplateView store', () => {
]);
});
});

describe('setInitialCredentialsSelection', () => {
beforeEach(() => {
setActivePinia(
createTestingPinia({
stubActions: false,
}),
);
});

it("selects no credentials when there isn't any available", () => {
// Setup
const credentialsStore = useCredentialsStore();
credentialsStore.setCredentialTypes([testData.credentialTypeTelegram]);
const templatesStore = useTemplatesStore();
templatesStore.addWorkflows([testData.fullShopifyTelegramTwitterTemplate]);

const setupTemplateStore = useSetupTemplateStore();
setupTemplateStore.setTemplateId(testData.fullShopifyTelegramTwitterTemplate.id.toString());

// Execute
setupTemplateStore.setInitialCredentialSelection();

expect(setupTemplateStore.selectedCredentialIdByName).toEqual({});
});

it("selects credential when there's only one", () => {
// Setup
const credentialsStore = useCredentialsStore();
credentialsStore.setCredentialTypes([testData.credentialTypeTelegram]);
credentialsStore.setCredentials([testData.credentialsTelegram1]);
const templatesStore = useTemplatesStore();
templatesStore.addWorkflows([testData.fullShopifyTelegramTwitterTemplate]);

const setupTemplateStore = useSetupTemplateStore();
setupTemplateStore.setTemplateId(testData.fullShopifyTelegramTwitterTemplate.id.toString());

// Execute
setupTemplateStore.setInitialCredentialSelection();

expect(setupTemplateStore.selectedCredentialIdByName).toEqual({
telegram_habot: 'YaSKdvEcT1TSFrrr1',
});
});

it('selects no credentials when there are more than 1 available', () => {
// Setup
const credentialsStore = useCredentialsStore();
credentialsStore.setCredentialTypes([testData.credentialTypeTelegram]);
credentialsStore.setCredentials([
testData.credentialsTelegram1,
testData.credentialsTelegram2,
]);
const templatesStore = useTemplatesStore();
templatesStore.addWorkflows([testData.fullShopifyTelegramTwitterTemplate]);

const setupTemplateStore = useSetupTemplateStore();
setupTemplateStore.setTemplateId(testData.fullShopifyTelegramTwitterTemplate.id.toString());

// Execute
setupTemplateStore.setInitialCredentialSelection();

expect(setupTemplateStore.selectedCredentialIdByName).toEqual({});
});

test.each([
['httpBasicAuth'],
['httpCustomAuth'],
['httpDigestAuth'],
['httpHeaderAuth'],
['oAuth1Api'],
['oAuth2Api'],
['httpQueryAuth'],
])('does not auto-select credentials for %s', (credentialType) => {
// Setup
const credentialsStore = useCredentialsStore();
credentialsStore.setCredentialTypes([testData.newCredentialType(credentialType)]);
credentialsStore.setCredentials([
testData.newCredential({
name: `${credentialType}Credential`,
type: credentialType,
}),
]);

const templatesStore = useTemplatesStore();
const workflow = testData.newFullOneNodeTemplate({
name: 'Test',
type: 'n8n-nodes-base.httpRequest',
typeVersion: 1,
credentials: {
[credentialType]: 'Test',
},
parameters: {},
position: [250, 300],
});
templatesStore.addWorkflows([workflow]);

const setupTemplateStore = useSetupTemplateStore();
setupTemplateStore.setTemplateId(workflow.id.toString());

// Execute
setupTemplateStore.setInitialCredentialSelection();

expect(setupTemplateStore.credentialUsages.length).toBe(1);
expect(setupTemplateStore.selectedCredentialIdByName).toEqual({});
});
});
});
Loading

0 comments on commit fe3417a

Please sign in to comment.