n8n/packages/nodes-base/nodes/Gong/test/Gong.node.test.ts
2024-10-16 10:23:09 +01:00

1080 lines
25 KiB
TypeScript

import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import type {
ICredentialDataDecryptedObject,
IDataObject,
IHttpRequestOptions,
} from 'n8n-workflow';
import { NodeConnectionType } from 'n8n-workflow';
import nock from 'nock';
import { gongApiResponse, gongNodeResponse } from './mocks';
import { FAKE_CREDENTIALS_DATA } from '../../../test/nodes/FakeCredentialsMap';
describe('Gong Node', () => {
const baseUrl = 'https://api.gong.io';
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('Credentials', () => {
const tests: WorkflowTestData[] = [
{
description: 'should use correct credentials',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
operation: 'get',
call: {
__rl: true,
value: '7782342274025937895',
mode: 'id',
},
options: {},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong gongApi',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
{
parameters: {
authentication: 'oAuth2',
operation: 'get',
call: {
__rl: true,
value: '7782342274025937896',
mode: 'id',
},
options: {},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong gongOAuth2Api',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongOAuth2Api: {
id: '2',
name: 'Gong account2',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong gongApi',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
'Gong gongApi': {
main: [
[
{
node: 'Gong gongOAuth2Api',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
'Gong gongApi': [[{ json: { metaData: gongNodeResponse.getCall[0].json.metaData } }]],
'Gong gongOAuth2Api': [
[{ json: { metaData: gongNodeResponse.getCall[0].json.metaData } }],
],
},
},
},
];
beforeAll(() => {
nock.disableNetConnect();
jest
.spyOn(Helpers.CredentialsHelper.prototype, 'authenticate')
.mockImplementation(
async (
credentials: ICredentialDataDecryptedObject,
typeName: string,
requestParams: IHttpRequestOptions,
): Promise<IHttpRequestOptions> => {
if (typeName === 'gongApi') {
return {
...requestParams,
headers: {
authorization:
'basic ' +
Buffer.from(`${credentials.accessKey}:${credentials.accessKeySecret}`).toString(
'base64',
),
},
};
} else if (typeName === 'gongOAuth2Api') {
return {
...requestParams,
headers: {
authorization:
'bearer ' + (credentials.oauthTokenData as IDataObject).access_token,
},
};
} else {
return requestParams;
}
},
);
});
afterAll(() => {
nock.restore();
jest.restoreAllMocks();
});
nock(baseUrl)
.post('/v2/calls/extensive', { filter: { callIds: ['7782342274025937895'] } })
.matchHeader(
'authorization',
'basic ' +
Buffer.from(
`${FAKE_CREDENTIALS_DATA.gongApi.accessKey}:${FAKE_CREDENTIALS_DATA.gongApi.accessKeySecret}`,
).toString('base64'),
)
.reply(200, {
...gongApiResponse.postCallsExtensive,
records: {},
calls: [{ metaData: gongApiResponse.postCallsExtensive.calls[0].metaData }],
})
.post('/v2/calls/extensive', { filter: { callIds: ['7782342274025937896'] } })
.matchHeader(
'authorization',
'bearer ' + FAKE_CREDENTIALS_DATA.gongOAuth2Api.oauthTokenData.access_token,
)
.reply(200, {
...gongApiResponse.postCallsExtensive,
records: {},
calls: [{ metaData: gongApiResponse.postCallsExtensive.calls[0].metaData }],
});
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes);
const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]),
);
expect(result.finished).toEqual(true);
});
});
describe('Call description', () => {
const tests: WorkflowTestData[] = [
{
description: 'should get call with no options true',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
operation: 'get',
call: {
__rl: true,
value: '7782342274025937895',
mode: 'id',
},
options: {},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [[{ json: { metaData: gongNodeResponse.getCall[0].json.metaData } }]],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 200,
requestBody: { filter: { callIds: ['7782342274025937895'] } },
responseBody: {
...gongApiResponse.postCallsExtensive,
records: {},
calls: [{ metaData: gongApiResponse.postCallsExtensive.calls[0].metaData }],
},
},
],
},
},
{
description: 'should get call with all options true',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
operation: 'get',
call: {
__rl: true,
value: '7782342274025937895',
mode: 'id',
},
options: {
properties: [
'pointsOfInterest',
'transcript',
'media',
'brief',
'publicComments',
'highlights',
'trackers',
'topics',
'structure',
'parties',
'callOutcome',
'outline',
'keyPoints',
],
},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [gongNodeResponse.getCall],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 200,
requestBody: {
filter: {
callIds: ['7782342274025937895'],
},
contentSelector: {
exposedFields: {
content: {
pointsOfInterest: true,
brief: true,
highlights: true,
keyPoints: true,
outline: true,
callOutcome: true,
structure: true,
trackers: true,
topics: true,
},
media: true,
collaboration: {
publicComments: true,
},
parties: true,
},
},
},
responseBody: {
...gongApiResponse.postCallsExtensive,
records: {},
},
},
{
method: 'post',
path: '/v2/calls/transcript',
statusCode: 200,
requestBody: {
filter: {
callIds: ['7782342274025937895'],
},
},
responseBody: gongApiResponse.postCallsTranscript,
},
],
},
},
{
description: 'should get all calls with filters',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
returnAll: true,
filters: {
fromDateTime: '2024-01-01T00:00:00Z',
toDateTime: '2024-12-31T00:00:00Z',
workspaceId: '3662366901393371750',
callIds: "={{ ['3662366901393371750', '3662366901393371751'] }}",
primaryUserIds: {
__rl: true,
value: '234599484848423',
mode: 'id',
},
},
options: {
properties: ['parties', 'topics'],
},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [gongNodeResponse.getAllCall],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 200,
requestBody: {
filter: {
fromDateTime: '2024-01-01T00:00:00.000Z',
toDateTime: '2024-12-31T00:00:00.000Z',
workspaceId: '3662366901393371750',
callIds: ['3662366901393371750', '3662366901393371751'],
primaryUserIds: ['234599484848423'],
},
contentSelector: {
exposedFields: {
parties: true,
content: {
topics: true,
},
},
},
cursor: undefined,
},
responseBody: {
...gongApiResponse.postCallsExtensive,
calls: [
{
metaData: {
...gongApiResponse.postCallsExtensive.calls[0].metaData,
parties: [...gongApiResponse.postCallsExtensive.calls[0].parties],
content: {
topics: [...gongApiResponse.postCallsExtensive.calls[0].content.topics],
},
},
},
],
},
},
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 200,
requestBody: {
filter: {
fromDateTime: '2024-01-01T00:00:00.000Z',
toDateTime: '2024-12-31T00:00:00.000Z',
workspaceId: '3662366901393371750',
callIds: ['3662366901393371750', '3662366901393371751'],
primaryUserIds: ['234599484848423'],
},
contentSelector: {
exposedFields: {
parties: true,
content: {
topics: true,
},
},
},
cursor:
'eyJhbGciOiJIUzI1NiJ9.eyJjYWxsSWQiM1M30.6qKwpOcvnuweTZmFRzYdtjs_YwJphJU4QIwWFM',
},
responseBody: {
...gongApiResponse.postCallsExtensive,
records: {},
calls: [
{
metaData: {
...gongApiResponse.postCallsExtensive.calls[0].metaData,
id: '7782342274025937896',
url: 'https://app.gong.io/call?id=7782342274025937896',
},
parties: [...gongApiResponse.postCallsExtensive.calls[0].parties],
content: {
topics: [...gongApiResponse.postCallsExtensive.calls[0].content.topics],
},
},
],
},
},
],
},
},
{
description: 'should get limit 50 calls with no options and filters',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
filters: {},
options: {},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [
Array.from({ length: 50 }, () => ({ ...gongNodeResponse.getAllCallNoOptions[0] })),
],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 200,
requestBody: {
filter: {},
},
responseBody: {
...gongApiResponse.postCallsExtensive,
calls: Array.from({ length: 100 }, () => ({
metaData: { ...gongApiResponse.postCallsExtensive.calls[0].metaData },
})),
},
},
],
},
},
{
description: 'should return empty result if no calls found for user',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
filters: {
primaryUserIds: {
__rl: true,
value: '234599484848423',
mode: 'id',
},
},
options: {},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [[{ json: {} }]],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 404,
requestBody: {
filter: {
primaryUserIds: ['234599484848423'],
},
cursor: undefined,
},
responseBody: {
requestId: 'thrhbxbkqiw41ma1cl',
errors: ['No calls found corresponding to the provided filters'],
},
},
],
},
},
{
description: 'should handle error response',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
filters: {
workspaceId: '623457276584335',
},
options: {},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
statusCode: 404,
requestBody: {
filter: {
workspaceId: '623457276584335',
},
},
responseBody: {
requestId: 'thrhbxbkqiw41ma1cl',
errors: ['No calls found corresponding to the provided filters'],
},
},
],
},
},
];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes);
if (testData.description === 'should handle error response') {
// Only matches error message
expect(() => Helpers.getResultNodeData(result, testData)).toThrowError(
'The resource you are requesting could not be found',
);
return;
}
const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]),
);
expect(result.finished).toEqual(true);
});
});
describe('User description', () => {
const tests: WorkflowTestData[] = [
{
description: 'should get user',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
resource: 'user',
user: {
__rl: true,
value: '234599484848423',
mode: 'id',
},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [gongNodeResponse.getUser],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/users/extensive',
statusCode: 200,
requestBody: { filter: { userIds: ['234599484848423'] } },
responseBody: {
...gongApiResponse.postUsersExtensive,
records: {},
},
},
],
},
},
{
description: 'should get all users',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
resource: 'user',
operation: 'getAll',
returnAll: true,
filters: {
createdFromDateTime: '2024-01-01T00:00:00Z',
createdToDateTime: '2024-12-31T00:00:00Z',
userIds: '234599484848423, 234599484848424',
},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [gongNodeResponse.getAllUser],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/users/extensive',
statusCode: 200,
requestBody: {
filter: {
createdFromDateTime: '2024-01-01T00:00:00.000Z',
createdToDateTime: '2024-12-31T00:00:00.000Z',
userIds: ['234599484848423', '234599484848424'],
},
},
responseBody: gongApiResponse.postUsersExtensive,
},
{
method: 'post',
path: '/v2/users/extensive',
statusCode: 200,
requestBody: {
filter: {
createdFromDateTime: '2024-01-01T00:00:00.000Z',
createdToDateTime: '2024-12-31T00:00:00.000Z',
userIds: ['234599484848423', '234599484848424'],
},
cursor:
'eyJhbGciOiJIUzI1NiJ9.eyJjYWxsSWQiM1M30.6qKwpOcvnuweTZmFRzYdtjs_YwJphJU4QIwWFM',
},
responseBody: {
...gongApiResponse.postUsersExtensive,
records: {},
users: [{ ...gongApiResponse.postUsersExtensive.users[0], id: '234599484848424' }],
},
},
],
},
},
{
description: 'should handle error response',
input: {
workflowData: {
nodes: [
{
parameters: {},
id: '416e4fc1-5055-4e61-854e-a6265256ac26',
name: "When clicking 'Test workflow'",
type: 'n8n-nodes-base.manualTrigger',
position: [820, 380],
typeVersion: 1,
},
{
parameters: {
resource: 'user',
operation: 'getAll',
filters: {
userIds: '234599484848423',
},
requestOptions: {},
},
id: 'c87d72ec-0683-4e32-9829-5e6ea1d1ee7d',
name: 'Gong',
type: 'n8n-nodes-base.gong',
typeVersion: 1,
position: [1040, 380],
credentials: {
gongApi: {
id: '1',
name: 'Gong account',
},
},
},
],
connections: {
"When clicking 'Test workflow'": {
main: [
[
{
node: 'Gong',
type: NodeConnectionType.Main,
index: 0,
},
],
],
},
},
},
},
output: {
nodeExecutionOrder: ['Start'],
nodeData: {
Gong: [],
},
},
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/users/extensive',
statusCode: 404,
requestBody: {
filter: {
userIds: ['234599484848423'],
},
},
responseBody: {
requestId: '26r8maav84ehguoddd7',
errors: ['The following userIds were not found: 234599484848423'],
},
},
],
},
},
];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes);
if (testData.description === 'should handle error response') {
expect(() => Helpers.getResultNodeData(result, testData)).toThrow(
"The Users IDs don't match any existing user",
);
return;
}
const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]),
);
expect(result.finished).toEqual(true);
});
});
});