refactor: Overhaul nodes-testing setup - Part 1 (no-changelog) (#14303)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2025-04-01 10:15:13 +02:00
committed by GitHub
parent f85b851851
commit 73e8d76e13
165 changed files with 3397 additions and 6453 deletions

View File

@@ -18,13 +18,12 @@ import type {
KnownNodesAndCredentials, KnownNodesAndCredentials,
INodeTypeBaseDescription, INodeTypeBaseDescription,
INodeTypeDescription, INodeTypeDescription,
INodeTypeData,
ICredentialTypeData,
LoadedClass, LoadedClass,
ICredentialType, ICredentialType,
INodeType, INodeType,
IVersionedNodeType, IVersionedNodeType,
INodeProperties, INodeProperties,
LoadedNodesAndCredentials,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { deepCopy, NodeConnectionTypes, UnexpectedError, UserError } from 'n8n-workflow'; import { deepCopy, NodeConnectionTypes, UnexpectedError, UserError } from 'n8n-workflow';
import path from 'path'; import path from 'path';
@@ -39,11 +38,6 @@ import {
} from '@/constants'; } from '@/constants';
import { isContainedWithin } from '@/utils/path-util'; import { isContainedWithin } from '@/utils/path-util';
interface LoadedNodesAndCredentials {
nodes: INodeTypeData;
credentials: ICredentialTypeData;
}
@Service() @Service()
export class LoadNodesAndCredentials { export class LoadNodesAndCredentials {
private known: KnownNodesAndCredentials = { nodes: {}, credentials: {} }; private known: KnownNodesAndCredentials = { nodes: {}, credentials: {} };

View File

@@ -1,6 +1,7 @@
const { NODE_ENV } = process.env; const { NODE_ENV } = process.env;
export const inProduction = NODE_ENV === 'production'; export const inProduction = NODE_ENV === 'production';
export const inDevelopment = !NODE_ENV || NODE_ENV === 'development'; export const inDevelopment = !NODE_ENV || NODE_ENV === 'development';
export const inTest = NODE_ENV === 'test';
export const CUSTOM_EXTENSION_ENV = 'N8N_CUSTOM_EXTENSIONS'; export const CUSTOM_EXTENSION_ENV = 'N8N_CUSTOM_EXTENSIONS';
export const PLACEHOLDER_EMPTY_EXECUTION_ID = '__UNKNOWN__'; export const PLACEHOLDER_EMPTY_EXECUTION_ID = '__UNKNOWN__';

View File

@@ -2,6 +2,10 @@ import vm from 'vm';
import { loadClassInIsolation } from '../load-class-in-isolation'; import { loadClassInIsolation } from '../load-class-in-isolation';
jest.mock('@/constants', () => ({
inTest: false,
}));
describe('loadClassInIsolation', () => { describe('loadClassInIsolation', () => {
const filePath = '/path/to/TestClass.js'; const filePath = '/path/to/TestClass.js';
const className = 'TestClass'; const className = 'TestClass';

View File

@@ -1,10 +1,19 @@
import { createContext, Script } from 'vm'; import { createContext, Script } from 'vm';
import { inTest } from '@/constants';
const context = createContext({ require }); const context = createContext({ require });
export const loadClassInIsolation = <T>(filePath: string, className: string) => { export const loadClassInIsolation = <T>(filePath: string, className: string) => {
if (process.platform === 'win32') { if (process.platform === 'win32') {
filePath = filePath.replace(/\\/g, '/'); filePath = filePath.replace(/\\/g, '/');
} }
const script = new Script(`new (require('${filePath}').${className})()`);
return script.runInContext(context) as T; // Note: Skip the isolation because it breaks nock mocks in tests
if (inTest) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access
return new (require(filePath)[className])() as T;
} else {
const script = new Script(`new (require('${filePath}').${className})()`);
return script.runInContext(context) as T;
}
}; };

View File

@@ -1,8 +1,8 @@
import type { WorkflowTestData } from 'n8n-workflow';
import nock from 'nock'; import nock from 'nock';
import { executeWorkflow } from '../ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '../Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '../types';
const records = [ const records = [
{ {
@@ -26,7 +26,7 @@ describe('Execute Airtable Node', () => {
{ {
description: 'List Airtable Records', description: 'List Airtable Records',
input: { input: {
workflowData: Helpers.readJsonFileSync('test/nodes/Airtable/workflow.json'), workflowData: Helpers.readJsonFileSync('nodes/Airtable/test/workflow.json'),
}, },
output: { output: {
nodeData: { nodeData: {
@@ -36,19 +36,9 @@ describe('Execute Airtable Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
for (const testData of tests) { for (const testData of tests) {
test(testData.description, async () => { test(testData.description, async () => {
try { await executeWorkflow(testData);
// execute workflow
await executeWorkflow(testData, nodeTypes);
} catch (error) {
expect(error).toBeUndefined();
expect(error.message).toEqual(
'The API Key connection was deprecated by Airtable, please use Access Token or OAuth2 instead.',
);
}
}); });
} }
}); });

View File

@@ -1,10 +1,9 @@
import { NodeConnectionTypes } from 'n8n-workflow'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow';
import assert from 'node:assert'; import assert from 'node:assert';
import qs from 'node:querystring'; import qs from 'node:querystring';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
describe('AwsSes Node', () => { describe('AwsSes Node', () => {
const email = 'test+user@example.com'; const email = 'test+user@example.com';
@@ -170,10 +169,8 @@ describe('AwsSes Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = Helpers.getResultNodeData(result, testData); const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]), expect(resultData).toEqual(testData.output.nodeData[nodeName]),

View File

@@ -1,5 +1,7 @@
import nock from 'nock'; import nock from 'nock';
import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers';
import { import {
createResponse, createResponse,
fieldsResponse, fieldsResponse,
@@ -7,18 +9,9 @@ import {
getResponse, getResponse,
updateResponse, updateResponse,
} from './apiResponses'; } from './apiResponses';
import {
setup,
equalityTest,
workflowToTests,
getWorkflowFilenames,
} from '../../../../test/nodes/Helpers';
describe('Baserow > Workflows', () => { describe('Baserow > Workflows', () => {
describe('Run workflow', () => { describe('Run workflow', () => {
const workflows = getWorkflowFilenames(__dirname);
const tests = workflowToTests(workflows);
beforeAll(() => { beforeAll(() => {
const mock = nock('https://api.baserow.io'); const mock = nock('https://api.baserow.io');
// Baserow > Get Token // Baserow > Get Token
@@ -54,10 +47,7 @@ describe('Baserow > Workflows', () => {
mock.delete('/api/database/rows/table/482710/3/').reply(200, {}); mock.delete('/api/database/rows/table/482710/3/').reply(200, {});
}); });
const nodeTypes = setup(tests); const workflows = getWorkflowFilenames(__dirname);
testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await equalityTest(testData, nodeTypes));
}
}); });
}); });

View File

@@ -1,16 +1,10 @@
/* eslint-disable @typescript-eslint/no-loop-func */ /* eslint-disable @typescript-eslint/no-loop-func */
import type { IDataObject } from 'n8n-workflow'; import type { IDataObject, WorkflowTestData } from 'n8n-workflow';
import os from 'node:os'; import os from 'node:os';
import path from 'path'; import path from 'path';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import { import { getResultNodeData, initBinaryDataService, readJsonFileSync } from '@test/nodes/Helpers';
getResultNodeData,
setup,
initBinaryDataService,
readJsonFileSync,
} from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
if (os.platform() !== 'win32') { if (os.platform() !== 'win32') {
describe('Execute Compression Node', () => { describe('Execute Compression Node', () => {
@@ -53,11 +47,9 @@ if (os.platform() !== 'win32') {
}, },
]; ];
const nodeTypes = setup(tests);
for (const testData of tests) { for (const testData of tests) {
test(testData.description, async () => { test(testData.description, async () => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = getResultNodeData(result, testData); const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => { resultNodeData.forEach(({ nodeName, resultData }) => {

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, channel => create', () => {
nock('https://discord.com/api/v10')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .post('/guilds/1168516062791340136/channels', { name: 'third', type: '0' })
.reply(200, {
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'POST') {
return {
id: '1168528323006181417', id: '1168528323006181417',
type: 0, type: 0,
last_message_id: null, last_message_id: null,
@@ -23,35 +18,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
position: 3, position: 3,
permission_overwrites: [], permission_overwrites: [],
nsfw: false, nsfw: false,
};
}
});
describe('Test DiscordV2, channel => create', () => {
const workflows = ['nodes/Discord/test/v2/node/channel/create.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Discord/test/v2/node/channel/create.workflow.json'];
expect(discordApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/guilds/1168516062791340136/channels',
{ name: 'third', type: '0' },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,53 +1,12 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api';
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest');
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'DELETE') {
return {
id: '1168528323006181417',
type: 0,
last_message_id: null,
flags: 0,
guild_id: '1168516062791340136',
name: 'third',
parent_id: null,
rate_limit_per_user: 0,
topic: null,
position: 3,
permission_overwrites: [],
nsfw: false,
};
}
});
describe('Test DiscordV2, channel => deleteChannel', () => { describe('Test DiscordV2, channel => deleteChannel', () => {
nock('https://discord.com/api/v10')
.delete('/channels/1168528323006181417')
.reply(200, { success: true });
const workflows = ['nodes/Discord/test/v2/node/channel/deleteChannel.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/channel/deleteChannel.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith('DELETE', '/channels/1168528323006181417');
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -61,18 +61,7 @@
"No Operation, do nothing": [ "No Operation, do nothing": [
{ {
"json": { "json": {
"id": "1168528323006181417", "success": true
"type": 0,
"last_message_id": null,
"flags": 0,
"guild_id": "1168516062791340136",
"name": "third",
"parent_id": null,
"rate_limit_per_user": 0,
"topic": null,
"position": 3,
"permission_overwrites": [],
"nsfw": false
} }
} }
] ]

View File

@@ -1,103 +1,28 @@
import type { INodeTypes, IRequestOptions } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/helpers';
// TODO: use nock
const requestApiSpy = jest.spyOn(transport, 'requestApi');
requestApiSpy.mockImplementation(
async (_options: IRequestOptions, _credentialType: string, endpoint: string) => {
if (endpoint === '/users/@me/guilds') {
return {
headers: {},
body: [
{
id: '1168516062791340136',
},
],
};
} else {
return {
headers: {},
body: {
id: '1168516240332034067',
type: 0,
last_message_id: null,
flags: 0,
guild_id: '1168516062791340136',
name: 'first',
parent_id: '1168516063340789831',
rate_limit_per_user: 0,
topic: null,
position: 1,
permission_overwrites: [],
nsfw: false,
},
};
}
},
);
describe('Test DiscordV2, channel => get', () => { describe('Test DiscordV2, channel => get', () => {
const workflows = ['nodes/Discord/test/v2/node/channel/get.workflow.json']; nock('https://discord.com/api/v10')
const tests = workflowToTests(workflows); .persist()
const nodeTypes = setup(tests); .get('/users/@me/guilds')
.reply(200, [{ id: '1168516062791340136' }])
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .get('/channels/1168516240332034067')
const { result } = await executeWorkflow(testData, types); .reply(200, {
id: '1168516240332034067',
const resultNodeData = getResultNodeData(result, testData); type: 0,
last_message_id: null,
resultNodeData.forEach(({ nodeName, resultData }) => { flags: 0,
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); guild_id: '1168516062791340136',
name: 'first',
parent_id: '1168516063340789831',
rate_limit_per_user: 0,
topic: null,
position: 1,
permission_overwrites: [],
nsfw: false,
}); });
expect(requestApiSpy).toHaveBeenCalledTimes(3); const workflows = ['nodes/Discord/test/v2/node/channel/get.workflow.json'];
expect(requestApiSpy).toHaveBeenCalledWith( testWorkflows(workflows);
{
body: undefined,
headers: {},
json: true,
method: 'GET',
qs: undefined,
url: 'https://discord.com/api/v10/users/@me/guilds',
},
'discordOAuth2Api',
'/users/@me/guilds',
);
expect(requestApiSpy).toHaveBeenCalledWith(
{
body: undefined,
headers: {},
json: true,
method: 'GET',
qs: undefined,
url: 'https://discord.com/api/v10/channels/1168516240332034067',
},
'discordOAuth2Api',
'/channels/1168516240332034067',
);
expect(requestApiSpy).toHaveBeenCalledWith(
{
body: undefined,
headers: {},
json: true,
method: 'GET',
qs: undefined,
url: 'https://discord.com/api/v10/channels/1168516240332034067',
},
'discordOAuth2Api',
'/channels/1168516240332034067',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, channel => getAll', () => {
nock('https://discord.com/api/v10')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .get('/guilds/1168516062791340136/channels')
.reply(200, [
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'GET') {
return [
{ {
id: '1168516063340789831', id: '1168516063340789831',
type: 4, type: 4,
@@ -99,34 +94,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
permission_overwrites: [], permission_overwrites: [],
nsfw: false, nsfw: false,
}, },
]; ]);
}
});
describe('Test DiscordV2, channel => getAll', () => {
const workflows = ['nodes/Discord/test/v2/node/channel/getAll.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/channel/getAll.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'GET',
'/guilds/1168516062791340136/channels',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,60 +1,23 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api';
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest');
discordApiRequestSpy.mockImplementation(async (method: string, _) => {
if (method === 'PATCH') {
return {
id: '1168516240332034067',
type: 0,
last_message_id: null,
flags: 0,
guild_id: '1168516062791340136',
name: 'first-channel',
parent_id: '1168516063340789831',
rate_limit_per_user: 30,
topic: 'This is channel topic',
position: 3,
permission_overwrites: [],
nsfw: true,
};
}
});
describe('Test DiscordV2, channel => update', () => { describe('Test DiscordV2, channel => update', () => {
nock('https://discord.com/api/v10').patch('/channels/1168516240332034067').reply(200, {
id: '1168516240332034067',
type: 0,
last_message_id: null,
flags: 0,
guild_id: '1168516062791340136',
name: 'first-channel',
parent_id: '1168516063340789831',
rate_limit_per_user: 30,
topic: 'This is channel topic',
position: 3,
permission_overwrites: [],
nsfw: true,
});
const workflows = ['nodes/Discord/test/v2/node/channel/update.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/channel/update.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith('PATCH', '/channels/1168516240332034067', {
name: 'First Channel',
nsfw: true,
parent_id: '1168516063340789831',
position: 3,
rate_limit_per_user: 30,
topic: 'This is channel topic',
});
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, member => getAll', () => {
nock('https://discord.com/api/v10')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .get('/guilds/1168516062791340136/members?limit=2')
.reply(200, [
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'GET') {
return [
{ {
user: { user: {
id: '470936827994570762', id: '470936827994570762',
@@ -46,36 +41,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
}, },
roles: ['1168518368526077992'], roles: ['1168518368526077992'],
}, },
]; ]);
}
});
describe('Test DiscordV2, member => getAll', () => {
const workflows = ['nodes/Discord/test/v2/node/member/getAll.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/member/getAll.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'GET',
'/guilds/1168516062791340136/members',
undefined,
{ limit: 2 },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,45 +1,12 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api';
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest');
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'PUT') {
return {
success: true,
};
}
});
describe('Test DiscordV2, member => roleAdd', () => { describe('Test DiscordV2, member => roleAdd', () => {
nock('https://discord.com/api/v10')
.put('/guilds/1168516062791340136/members/470936827994570762/roles/1168772374540320890')
.reply(200, { success: true });
const workflows = ['nodes/Discord/test/v2/node/member/roleAdd.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/member/roleAdd.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'PUT',
'/guilds/1168516062791340136/members/470936827994570762/roles/1168772374540320890',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,53 +1,13 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api';
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest');
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'DELETE') {
return {
success: true,
};
}
});
describe('Test DiscordV2, member => roleRemove', () => { describe('Test DiscordV2, member => roleRemove', () => {
nock('https://discord.com/api/v10')
.persist()
.delete(/\/guilds\/1168516062791340136\/members\/470936827994570762\/roles\/\d+/)
.reply(200, { success: true });
const workflows = ['nodes/Discord/test/v2/node/member/roleRemove.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/member/roleRemove.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(3);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'DELETE',
'/guilds/1168516062791340136/members/470936827994570762/roles/1168773588963299428',
);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'DELETE',
'/guilds/1168516062791340136/members/470936827994570762/roles/1168773645800308756',
);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'DELETE',
'/guilds/1168516062791340136/members/470936827994570762/roles/1168772374540320890',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,45 +1,12 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api';
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest');
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'DELETE') {
return {
success: true,
};
}
});
describe('Test DiscordV2, message => deleteMessage', () => { describe('Test DiscordV2, message => deleteMessage', () => {
nock('https://discord.com/api/v10')
.delete('/channels/1168516240332034067/messages/1168776343194972210')
.reply(200, { success: true });
const workflows = ['nodes/Discord/test/v2/node/message/deleteMessage.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/message/deleteMessage.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'DELETE',
'/channels/1168516240332034067/messages/1168776343194972210',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, message => get', () => {
nock('https://discord.com/api/v10')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .get('/channels/1168516240332034067/messages/1168777380144369718')
.reply(200, {
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'GET') {
return {
id: '1168777380144369718', id: '1168777380144369718',
channel_id: '1168516240332034067', channel_id: '1168516240332034067',
author: { author: {
@@ -31,34 +26,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
content: 'msg 3', content: 'msg 3',
timestamp: '2023-10-31T05:04:02.260000+00:00', timestamp: '2023-10-31T05:04:02.260000+00:00',
type: 0, type: 0,
};
}
});
describe('Test DiscordV2, message => get', () => {
const workflows = ['nodes/Discord/test/v2/node/message/get.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Discord/test/v2/node/message/get.workflow.json'];
expect(discordApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'GET',
'/channels/1168516240332034067/messages/1168777380144369718',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, message => getAll', () => {
nock('https://discord.com/api/v10')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .get('/channels/1168516240332034067/messages?limit=1')
.reply(200, [
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'GET') {
return [
{ {
id: '1168784010269433998', id: '1168784010269433998',
type: 0, type: 0,
@@ -54,36 +49,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
flags: 0, flags: 0,
components: [], components: [],
}, },
]; ]);
}
});
describe('Test DiscordV2, message => getAll', () => {
const workflows = ['nodes/Discord/test/v2/node/message/getAll.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/message/getAll.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'GET',
'/channels/1168516240332034067/messages',
undefined,
{ limit: 1 },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,45 +1,12 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api';
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest');
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'PUT') {
return {
success: true,
};
}
});
describe('Test DiscordV2, message => react', () => { describe('Test DiscordV2, message => react', () => {
nock('https://discord.com/api/v10')
.put('/channels/1168516240332034067/messages/1168777380144369718/reactions/%F0%9F%98%80/@me')
.reply(200, { success: true });
const workflows = ['nodes/Discord/test/v2/node/message/react.workflow.json']; const workflows = ['nodes/Discord/test/v2/node/message/react.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1);
expect(discordApiRequestSpy).toHaveBeenCalledWith(
'PUT',
'/channels/1168516240332034067/messages/1168777380144369718/reactions/%F0%9F%98%80/@me',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,22 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, message => send', () => {
nock('https://discord.com/api/v10')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .post('/channels/1168516240332034067/messages', {
content: 'msg 4',
discordApiRequestSpy.mockImplementation(async (method: string) => { embeds: [
if (method === 'POST') { {
return { author: { name: 'Me' },
color: 2112935,
description: 'description',
timestamp: '2023-10-30T22:00:00.000Z',
title: 'Some Title',
},
],
})
.reply(200, {
id: '1168784010269433998', id: '1168784010269433998',
type: 0, type: 0,
content: 'msg 4', content: 'msg 4',
@@ -53,46 +59,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
flags: 0, flags: 0,
components: [], components: [],
referenced_message: null, referenced_message: null,
};
}
});
describe('Test DiscordV2, message => send', () => {
const workflows = ['nodes/Discord/test/v2/node/message/send.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Discord/test/v2/node/message/send.workflow.json'];
expect(discordApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/channels/1168516240332034067/messages',
{
content: 'msg 4',
embeds: [
{
author: { name: 'Me' },
color: 2112935,
description: 'description',
timestamp: '2023-10-30T22:00:00.000Z',
title: 'Some Title',
},
],
},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport/discord.api'; describe('Test DiscordV2, webhook => sendLegacy', () => {
nock('https://discord.com')
const discordApiRequestSpy = jest.spyOn(transport, 'discordApiRequest'); .post('/webhook?wait=true')
.reply(200, {
discordApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'POST') {
return {
id: '1168768986385747999', id: '1168768986385747999',
type: 0, type: 0,
content: 'TEST Message', content: 'TEST Message',
@@ -47,49 +42,8 @@ discordApiRequestSpy.mockImplementation(async (method: string) => {
flags: 4096, flags: 4096,
components: [], components: [],
webhook_id: '1153265494955135077', webhook_id: '1153265494955135077',
};
}
});
describe('Test DiscordV2, webhook => sendLegacy', () => {
const workflows = ['nodes/Discord/test/v2/node/webhook/sendLegacy.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(discordApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Discord/test/v2/node/webhook/sendLegacy.workflow.json'];
expect(discordApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'',
{
content: 'TEST Message',
embeds: [
{
author: { name: 'Michael' },
color: 10930459,
description: 'some description',
timestamp: '2023-10-17T21:00:00.000Z',
},
],
flags: 4096,
tts: true,
username: 'TEST_USER',
},
{ wait: true },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,7 +1,8 @@
import { mock } from 'jest-mock-extended'; import { mock } from 'jest-mock-extended';
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { testWorkflows, getWorkflowFilenames } from '../../../test/nodes/Helpers'; import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers';
import { ExecutionData } from '../ExecutionData.node'; import { ExecutionData } from '../ExecutionData.node';
describe('ExecutionData Node', () => { describe('ExecutionData Node', () => {

View File

@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-loop-func */ /* eslint-disable @typescript-eslint/no-loop-func */
import type { WorkflowTestData } from 'n8n-workflow';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
describe('Test ReadWriteFile Node', () => { describe('Test ReadWriteFile Node', () => {
beforeEach(async () => { beforeEach(async () => {
@@ -84,11 +85,9 @@ describe('Test ReadWriteFile Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
for (const testData of tests) { for (const testData of tests) {
test(testData.description, async () => { test(testData.description, async () => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = Helpers.getResultNodeData(result, testData); const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => { resultNodeData.forEach(({ nodeName, resultData }) => {

View File

@@ -62,9 +62,9 @@ describe('Test Github Node', () => {
jest.useFakeTimers({ doNotFake: ['nextTick'], now }); jest.useFakeTimers({ doNotFake: ['nextTick'], now });
await initBinaryDataService(); await initBinaryDataService();
}); });
beforeEach(async () => { beforeEach(async () => {
const baseUrl = 'https://api.github.com'; const baseUrl = 'https://api.github.com';
nock.cleanAll();
nock(baseUrl) nock(baseUrl)
.persist() .persist()
.defaultReplyHeaders({ 'Content-Type': 'application/json' }) .defaultReplyHeaders({ 'Content-Type': 'application/json' })
@@ -83,9 +83,6 @@ describe('Test Github Node', () => {
.reply(200, {}); .reply(200, {});
}); });
afterEach(() => {
nock.cleanAll();
});
testWorkflows(workflows); testWorkflows(workflows);
}); });
}); });

View File

@@ -2,27 +2,19 @@ import type {
ICredentialDataDecryptedObject, ICredentialDataDecryptedObject,
IDataObject, IDataObject,
IHttpRequestOptions, IHttpRequestOptions,
WorkflowTestData,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow'; import { NodeConnectionTypes } from 'n8n-workflow';
import nock from 'nock';
import { CredentialsHelper } from '@test/nodes/credentials-helper';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import { gongApiResponse, gongNodeResponse } from './mocks'; import { gongApiResponse, gongNodeResponse } from './mocks';
import { FAKE_CREDENTIALS_DATA } from '../../../test/nodes/FakeCredentialsMap';
describe('Gong Node', () => { describe('Gong Node', () => {
const baseUrl = 'https://api.gong.io'; const baseUrl = 'https://api.gong.io';
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('Credentials', () => { describe('Credentials', () => {
const tests: WorkflowTestData[] = [ const tests: WorkflowTestData[] = [
{ {
@@ -121,12 +113,39 @@ describe('Gong Node', () => {
], ],
}, },
}, },
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/v2/calls/extensive',
requestBody: { filter: { callIds: ['7782342274025937895'] } },
statusCode: 200,
responseBody: {
...gongApiResponse.postCallsExtensive,
records: {},
calls: [{ metaData: gongApiResponse.postCallsExtensive.calls[0].metaData }],
},
},
{
method: 'post',
path: '/v2/calls/extensive',
requestBody: { filter: { callIds: ['7782342274025937896'] } },
statusCode: 200,
responseBody: {
...gongApiResponse.postCallsExtensive,
records: {},
calls: [{ metaData: gongApiResponse.postCallsExtensive.calls[0].metaData }],
},
},
],
},
}, },
]; ];
beforeAll(() => { beforeAll(() => {
jest jest
.spyOn(Helpers.CredentialsHelper.prototype, 'authenticate') .spyOn(CredentialsHelper.prototype, 'authenticate')
.mockImplementation( .mockImplementation(
async ( async (
credentials: ICredentialDataDecryptedObject, credentials: ICredentialDataDecryptedObject,
@@ -159,35 +178,8 @@ describe('Gong Node', () => {
); );
}); });
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) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = Helpers.getResultNodeData(result, testData); const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]), expect(resultData).toEqual(testData.output.nodeData[nodeName]),
@@ -780,10 +772,8 @@ describe('Gong Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
if (testData.description === 'should handle error response') { if (testData.description === 'should handle error response') {
// Only matches error message // Only matches error message
@@ -1051,10 +1041,8 @@ describe('Gong Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
if (testData.description === 'should handle error response') { if (testData.description === 'should handle error response') {
expect(() => Helpers.getResultNodeData(result, testData)).toThrow( expect(() => Helpers.getResultNodeData(result, testData)).toThrow(

View File

@@ -1,67 +1,42 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../v2/transport'; jest.mock('jsonwebtoken', () => ({
sign: jest.fn().mockReturnValue('signature'),
jest.mock('../../../v2/transport', () => { }));
const originalModule = jest.requireActual('../../../v2/transport');
return {
...originalModule,
googleBigQueryApiRequest: jest.fn(async (method: IHttpRequestMethods, resource: string) => {
if (resource === '/v2/projects/test-project/jobs' && method === 'POST') {
return {
jobReference: {
jobId: 'job_123',
},
status: {
state: 'DONE',
},
};
}
if (resource === '/v2/projects/test-project/queries/job_123' && method === 'GET') {
return {};
}
}),
googleBigQueryApiRequestAllItems: jest.fn(async () => ({ rows: [], schema: {} })),
};
});
describe('Test Google BigQuery V2, executeQuery', () => { describe('Test Google BigQuery V2, executeQuery', () => {
const workflows = ['nodes/Google/BigQuery/test/v2/node/executeQuery.workflow.json']; nock('https://oauth2.googleapis.com')
const tests = workflowToTests(workflows); .persist()
const nodeTypes = setup(tests); .post(
'/token',
'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=signature',
)
.reply(200, { access_token: 'token' });
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { nock('https://bigquery.googleapis.com/bigquery')
const { result } = await executeWorkflow(testData, types); .post('/v2/projects/test-project/jobs', {
configuration: {
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledTimes(1); query: {
expect(transport.googleBigQueryApiRequestAllItems).toHaveBeenCalledTimes(1); query: 'SELECT * FROM bigquery_node_dev_test_dataset.test_json;',
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledWith( useLegacySql: false,
'POST',
'/v2/projects/test-project/jobs',
{
configuration: {
query: {
query: 'SELECT * FROM bigquery_node_dev_test_dataset.test_json;',
useLegacySql: false,
},
}, },
}, },
); })
expect(transport.googleBigQueryApiRequestAllItems).toHaveBeenCalledWith( .reply(200, {
'GET', jobReference: {
'/v2/projects/test-project/queries/job_123', jobId: 'job_123',
undefined, },
{ location: undefined, maxResults: 1000, timeoutMs: 10000 }, status: {
); state: 'DONE',
},
})
.get('/v2/projects/test-project/queries/job_123')
.reply(200)
.get('/v2/projects/test-project/queries/job_123?maxResults=1000&timeoutMs=10000')
.reply(200, { rows: [], schema: {} });
expect(result.finished).toEqual(true); const workflows = ['nodes/Google/BigQuery/test/v2/node/executeQuery.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,58 +1,31 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../v2/transport'; jest.mock('jsonwebtoken', () => ({
sign: jest.fn().mockReturnValue('signature'),
jest.mock('../../../v2/transport', () => { }));
const originalModule = jest.requireActual('../../../v2/transport');
return {
...originalModule,
googleBigQueryApiRequest: jest.fn(async (method: IHttpRequestMethods, resource: string) => {
if (
resource ===
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/num_text' &&
method === 'GET'
) {
return {
schema: {
fields: [
{ name: 'id', type: 'INT' },
{ name: 'test', type: 'STRING' },
],
},
};
}
if (
resource ===
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/num_text/insertAll' &&
method === 'POST'
) {
return { kind: 'bigquery#tableDataInsertAllResponse' };
}
}),
googleApiRequestAllItems: jest.fn(async () => {}),
};
});
describe('Test Google BigQuery V2, insert auto map', () => { describe('Test Google BigQuery V2, insert auto map', () => {
const workflows = ['nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.workflow.json']; nock('https://oauth2.googleapis.com')
const tests = workflowToTests(workflows); .persist()
const nodeTypes = setup(tests); .post(
'/token',
'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=signature',
)
.reply(200, { access_token: 'token' });
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { nock('https://bigquery.googleapis.com/bigquery')
const { result } = await executeWorkflow(testData, types); .get('/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/num_text')
.reply(200, {
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledTimes(2); schema: {
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledWith( fields: [
'GET', { name: 'id', type: 'INT' },
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/num_text', { name: 'test', type: 'STRING' },
{}, ],
); },
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledWith( })
'POST', .post(
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/num_text/insertAll', '/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/num_text/insertAll',
{ {
rows: [ rows: [
@@ -62,12 +35,13 @@ describe('Test Google BigQuery V2, insert auto map', () => {
], ],
traceId: 'trace_id', traceId: 'trace_id',
}, },
); )
.reply(200, [
{ kind: 'bigquery#tableDataInsertAllResponse' },
{ kind: 'bigquery#tableDataInsertAllResponse' },
{ kind: 'bigquery#tableDataInsertAllResponse' },
]);
expect(result.finished).toEqual(true); const workflows = ['nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,70 +1,40 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../v2/transport'; jest.mock('jsonwebtoken', () => ({
sign: jest.fn().mockReturnValue('signature'),
jest.mock('../../../v2/transport', () => { }));
const originalModule = jest.requireActual('../../../v2/transport');
return {
...originalModule,
googleBigQueryApiRequest: jest.fn(async (method: IHttpRequestMethods, resource: string) => {
if (
resource ===
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/test_json' &&
method === 'GET'
) {
return {
schema: {
fields: [
{ name: 'json', type: 'JSON' },
{ name: 'name with space', type: 'STRING' },
{ name: 'active', type: 'BOOLEAN' },
],
},
};
}
if (
resource ===
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/test_json/insertAll' &&
method === 'POST'
) {
return { kind: 'bigquery#tableDataInsertAllResponse' };
}
}),
googleApiRequestAllItems: jest.fn(async () => {}),
};
});
describe('Test Google BigQuery V2, insert define manually', () => { describe('Test Google BigQuery V2, insert define manually', () => {
const workflows = ['nodes/Google/BigQuery/test/v2/node/insert.manualMode.workflow.json']; nock('https://oauth2.googleapis.com')
const tests = workflowToTests(workflows); .persist()
const nodeTypes = setup(tests); .post(
'/token',
'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=signature',
)
.reply(200, { access_token: 'token' });
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { nock('https://bigquery.googleapis.com/bigquery')
const { result } = await executeWorkflow(testData, types); .get('/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/test_json')
.reply(200, {
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledTimes(2); schema: {
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledWith( fields: [
'GET', { name: 'json', type: 'JSON' },
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/test_json', { name: 'name with space', type: 'STRING' },
{}, { name: 'active', type: 'BOOLEAN' },
); ],
expect(transport.googleBigQueryApiRequest).toHaveBeenCalledWith( },
'POST', })
.post(
'/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/test_json/insertAll', '/v2/projects/test-project/datasets/bigquery_node_dev_test_dataset/tables/test_json/insertAll',
{ {
rows: [{ json: { active: 'true', json: '{"test": 1}', 'name with space': 'some name' } }], rows: [{ json: { active: 'true', json: '{"test": 1}', 'name with space': 'some name' } }],
traceId: 'trace_id', traceId: 'trace_id',
}, },
); )
.reply(200, [{ kind: 'bigquery#tableDataInsertAllResponse' }]);
expect(result.finished).toEqual(true); const workflows = ['nodes/Google/BigQuery/test/v2/node/insert.manualMode.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -12,12 +12,9 @@ describe('Test Gmail Node v1', () => {
jest jest
.useFakeTimers({ doNotFake: ['setImmediate', 'nextTick'] }) .useFakeTimers({ doNotFake: ['setImmediate', 'nextTick'] })
.setSystemTime(new Date('2024-12-16 12:34:56.789Z')); .setSystemTime(new Date('2024-12-16 12:34:56.789Z'));
nock.disableNetConnect();
}); });
afterAll(() => { afterAll(() => {
nock.restore();
jest.resetAllMocks(); jest.resetAllMocks();
}); });

View File

@@ -14,8 +14,6 @@ describe('Test Gmail Node v2', () => {
jest jest
.useFakeTimers({ doNotFake: ['setImmediate', 'nextTick'] }) .useFakeTimers({ doNotFake: ['setImmediate', 'nextTick'] })
.setSystemTime(new Date('2024-12-16 12:34:56.789Z')); .setSystemTime(new Date('2024-12-16 12:34:56.789Z'));
nock.disableNetConnect();
}); });
describe('Messages', () => { describe('Messages', () => {

View File

@@ -1,18 +1,9 @@
/* eslint-disable n8n-nodes-base/node-filename-against-convention */ /* eslint-disable n8n-nodes-base/node-filename-against-convention */
import nock from 'nock'; import nock from 'nock';
import { import { getWorkflowFilenames, initBinaryDataService, testWorkflows } from '@test/nodes/Helpers';
equalityTest,
getWorkflowFilenames,
initBinaryDataService,
setup,
workflowToTests,
} from '@test/nodes/Helpers';
describe('GraphQL Node', () => { describe('GraphQL Node', () => {
const workflows = getWorkflowFilenames(__dirname);
const workflowTests = workflowToTests(workflows);
const baseUrl = 'https://api.n8n.io/'; const baseUrl = 'https://api.n8n.io/';
beforeAll(async () => { beforeAll(async () => {
@@ -69,9 +60,6 @@ describe('GraphQL Node', () => {
}); });
}); });
const nodeTypes = setup(workflowTests); const workflows = getWorkflowFilenames(__dirname);
testWorkflows(workflows);
for (const workflow of workflowTests) {
test(workflow.description, async () => await equalityTest(workflow, nodeTypes));
}
}); });

View File

@@ -1,17 +1,8 @@
import nock from 'nock'; import nock from 'nock';
import { import { getWorkflowFilenames, initBinaryDataService, testWorkflows } from '@test/nodes/Helpers';
setup,
equalityTest,
workflowToTests,
getWorkflowFilenames,
initBinaryDataService,
} from '@test/nodes/Helpers';
describe('Test Binary Data Download', () => { describe('Test Binary Data Download', () => {
const workflows = getWorkflowFilenames(__dirname);
const tests = workflowToTests(workflows);
const baseUrl = 'https://dummy.domain'; const baseUrl = 'https://dummy.domain';
beforeAll(async () => { beforeAll(async () => {
@@ -31,9 +22,7 @@ describe('Test Binary Data Download', () => {
'content-disposition': 'attachment; filename="testing.jpg"', 'content-disposition': 'attachment; filename="testing.jpg"',
}); });
}); });
const nodeTypes = setup(tests);
for (const testData of tests) { const workflows = getWorkflowFilenames(__dirname);
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,17 +1,8 @@
import nock from 'nock'; import nock from 'nock';
import { import { getWorkflowFilenames, initBinaryDataService, testWorkflows } from '@test/nodes/Helpers';
setup,
equalityTest,
workflowToTests,
getWorkflowFilenames,
initBinaryDataService,
} from '@test/nodes/Helpers';
describe('Test Response Encoding', () => { describe('Test Response Encoding', () => {
const workflows = getWorkflowFilenames(__dirname);
const tests = workflowToTests(workflows);
const baseUrl = 'https://dummy.domain'; const baseUrl = 'https://dummy.domain';
const payload = Buffer.from( const payload = Buffer.from(
'El rápido zorro marrón salta sobre el perro perezoso. ¡Qué bello día en París! Árbol, cañón, façade.', 'El rápido zorro marrón salta sobre el perro perezoso. ¡Qué bello día en París! Árbol, cañón, façade.',
@@ -26,9 +17,7 @@ describe('Test Response Encoding', () => {
.get('/index.html') .get('/index.html')
.reply(200, payload, { 'content-type': 'text/plain; charset=latin1' }); .reply(200, payload, { 'content-type': 'text/plain; charset=latin1' });
}); });
const nodeTypes = setup(tests);
for (const testData of tests) { const workflows = getWorkflowFilenames(__dirname);
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,17 +1,8 @@
import nock from 'nock'; import nock from 'nock';
import { import { getWorkflowFilenames, initBinaryDataService, testWorkflows } from '@test/nodes/Helpers';
setup,
equalityTest,
workflowToTests,
getWorkflowFilenames,
initBinaryDataService,
} from '@test/nodes/Helpers';
describe('Test Quoted Response Encoding', () => { describe('Test Quoted Response Encoding', () => {
const workflows = getWorkflowFilenames(__dirname);
const tests = workflowToTests(workflows);
const baseUrl = 'https://dummy.domain'; const baseUrl = 'https://dummy.domain';
const payload = Buffer.from( const payload = Buffer.from(
'El rápido zorro marrón salta sobre el perro perezoso. ¡Qué bello día en París! Árbol, cañón, façade.', 'El rápido zorro marrón salta sobre el perro perezoso. ¡Qué bello día en París! Árbol, cañón, façade.',
@@ -26,9 +17,7 @@ describe('Test Quoted Response Encoding', () => {
.get('/index.html') .get('/index.html')
.reply(200, payload, { 'content-type': 'text/plain; charset="latin1"' }); .reply(200, payload, { 'content-type': 'text/plain; charset="latin1"' });
}); });
const nodeTypes = setup(tests);
for (const testData of tests) { const workflows = getWorkflowFilenames(__dirname);
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,18 +1,9 @@
import nock from 'nock'; import nock from 'nock';
import { parse as parseUrl } from 'url'; import { parse as parseUrl } from 'url';
import { import { initBinaryDataService, getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers';
initBinaryDataService,
setup,
equalityTest,
workflowToTests,
getWorkflowFilenames,
} from '@test/nodes/Helpers';
describe('Test HTTP Request Node', () => { describe('Test HTTP Request Node', () => {
const workflows = getWorkflowFilenames(__dirname);
const tests = workflowToTests(workflows);
const baseUrl = 'https://dummyjson.com'; const baseUrl = 'https://dummyjson.com';
beforeAll(async () => { beforeAll(async () => {
@@ -191,9 +182,7 @@ describe('Test HTTP Request Node', () => {
return getPaginationReturnData.call(this, limit, skip); return getPaginationReturnData.call(this, limit, skip);
}); });
}); });
const nodeTypes = setup(tests);
for (const testData of tests) { const workflows = getWorkflowFilenames(__dirname);
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,12 +1,8 @@
/* eslint-disable @typescript-eslint/no-loop-func */ /* eslint-disable @typescript-eslint/no-loop-func */
import type { WorkflowTestData } from 'n8n-workflow';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import { import { getResultNodeData, readJsonFileSync, initBinaryDataService } from '@test/nodes/Helpers';
getResultNodeData,
setup,
readJsonFileSync,
initBinaryDataService,
} from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
describe('Execute iCalendar Node', () => { describe('Execute iCalendar Node', () => {
beforeEach(async () => { beforeEach(async () => {
@@ -43,11 +39,10 @@ describe('Execute iCalendar Node', () => {
}, },
}, },
]; ];
const nodeTypes = setup(tests);
for (const testData of tests) { for (const testData of tests) {
test(testData.description, async () => { test(testData.description, async () => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = getResultNodeData(result, testData); const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => { resultNodeData.forEach(({ nodeName, resultData }) => {

View File

@@ -1,6 +1,7 @@
import nock from 'nock'; import nock from 'nock';
import { getWorkflowFilenames, testWorkflows } from '../../../../test/nodes/Helpers'; import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers';
import { import {
getCreateResponseClassic, getCreateResponseClassic,
getSubscriberResponseClassic, getSubscriberResponseClassic,

View File

@@ -1,6 +1,7 @@
import nock from 'nock'; import nock from 'nock';
import { getWorkflowFilenames, testWorkflows } from '../../../../test/nodes/Helpers'; import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers';
import { import {
getCreateResponseV2, getCreateResponseV2,
getSubscriberResponseV2, getSubscriberResponseV2,

View File

@@ -1,6 +1,7 @@
import type { IDataObject, INode } from 'n8n-workflow'; import type { IDataObject, INode } from 'n8n-workflow';
import { createMockExecuteFunction } from '../../../../test/nodes/Helpers'; import { createMockExecuteFunction } from '@test/nodes/Helpers';
import * as mode from '../../v3/actions/mode'; import * as mode from '../../v3/actions/mode';
const node: INode = { const node: INode = {

View File

@@ -1,22 +1,13 @@
import { NodeConnectionTypes } from 'n8n-workflow'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow';
import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks'; import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks';
describe('Microsoft Entra Node', () => { describe('Microsoft Entra Node', () => {
const baseUrl = 'https://graph.microsoft.com/v1.0'; const baseUrl = 'https://graph.microsoft.com/v1.0';
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('Group description', () => { describe('Group description', () => {
const tests: WorkflowTestData[] = [ const tests: WorkflowTestData[] = [
{ {
@@ -760,10 +751,8 @@ describe('Microsoft Entra Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = Helpers.getResultNodeData(result, testData); const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => resultNodeData.forEach(({ nodeName, resultData }) =>

View File

@@ -3,28 +3,20 @@ import type {
IDataObject, IDataObject,
IHttpRequestOptions, IHttpRequestOptions,
ILoadOptionsFunctions, ILoadOptionsFunctions,
WorkflowTestData,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow'; import { NodeConnectionTypes } from 'n8n-workflow';
import nock from 'nock';
import { CredentialsHelper } from '@test/nodes/credentials-helper';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks'; import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks';
import { FAKE_CREDENTIALS_DATA } from '../../../../test/nodes/FakeCredentialsMap';
import { MicrosoftEntra } from '../MicrosoftEntra.node'; import { MicrosoftEntra } from '../MicrosoftEntra.node';
describe('Microsoft Entra Node', () => { describe('Microsoft Entra Node', () => {
const baseUrl = 'https://graph.microsoft.com/v1.0'; const baseUrl = 'https://graph.microsoft.com/v1.0';
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('Credentials', () => { describe('Credentials', () => {
const tests: WorkflowTestData[] = [ const tests: WorkflowTestData[] = [
{ {
@@ -87,12 +79,25 @@ describe('Microsoft Entra Node', () => {
'Micosoft Entra ID': [microsoftEntraNodeResponse.getGroup], 'Micosoft Entra ID': [microsoftEntraNodeResponse.getGroup],
}, },
}, },
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: `/groups/${microsoftEntraApiResponse.getGroup.id}`,
statusCode: 200,
responseBody: {
...microsoftEntraApiResponse.getGroup,
},
},
],
},
}, },
]; ];
beforeAll(() => { beforeAll(() => {
jest jest
.spyOn(Helpers.CredentialsHelper.prototype, 'authenticate') .spyOn(CredentialsHelper.prototype, 'authenticate')
.mockImplementation( .mockImplementation(
async ( async (
credentials: ICredentialDataDecryptedObject, credentials: ICredentialDataDecryptedObject,
@@ -114,20 +119,8 @@ describe('Microsoft Entra Node', () => {
); );
}); });
nock(baseUrl)
.get(`/groups/${microsoftEntraApiResponse.getGroup.id}`)
.matchHeader(
'authorization',
'bearer ' + FAKE_CREDENTIALS_DATA.microsoftEntraOAuth2Api.oauthTokenData.access_token,
)
.reply(200, {
...microsoftEntraApiResponse.getGroup,
});
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = Helpers.getResultNodeData(result, testData); const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => resultNodeData.forEach(({ nodeName, resultData }) =>
expect(resultData).toEqual(testData.output.nodeData[nodeName]), expect(resultData).toEqual(testData.output.nodeData[nodeName]),

View File

@@ -1,22 +1,13 @@
import { NodeConnectionTypes } from 'n8n-workflow'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow';
import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';
import * as Helpers from '@test/nodes/Helpers'; import * as Helpers from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks'; import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks';
describe('Microsoft Entra Node', () => { describe('Microsoft Entra Node', () => {
const baseUrl = 'https://graph.microsoft.com/v1.0'; const baseUrl = 'https://graph.microsoft.com/v1.0';
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('User description', () => { describe('User description', () => {
const tests: WorkflowTestData[] = [ const tests: WorkflowTestData[] = [
{ {
@@ -1146,10 +1137,8 @@ describe('Microsoft Entra Node', () => {
}, },
]; ];
const nodeTypes = Helpers.setup(tests);
test.each(tests)('$description', async (testData) => { test.each(tests)('$description', async (testData) => {
const { result } = await executeWorkflow(testData, nodeTypes); const { result } = await executeWorkflow(testData);
const resultNodeData = Helpers.getResultNodeData(result, testData); const resultNodeData = Helpers.getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => resultNodeData.forEach(({ nodeName, resultData }) =>

View File

@@ -1,60 +1,27 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'POST') {
return {
style: 'TableStyleMedium2',
name: 'Table3',
showFilterButton: true,
id: '{317CA469-7D1C-4A5D-9B0B-424444BF0336}',
highlightLastColumn: false,
highlightFirstColumn: false,
legacyId: '3',
showBandedColumns: false,
showBandedRows: true,
showHeaders: true,
showTotals: false,
};
}
}),
};
});
describe('Test MicrosoftExcelV2, table => addTable', () => { describe('Test MicrosoftExcelV2, table => addTable', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/addTable.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/tables/add',
{ address: 'A1:D4', hasHeaders: true },
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { )
const { result } = await executeWorkflow(testData, types); .reply(200, {
style: 'TableStyleMedium2',
const resultNodeData = getResultNodeData(result, testData); name: 'Table3',
showFilterButton: true,
resultNodeData.forEach(({ nodeName, resultData }) => { id: '{317CA469-7D1C-4A5D-9B0B-424444BF0336}',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); highlightLastColumn: false,
highlightFirstColumn: false,
legacyId: '3',
showBandedColumns: false,
showBandedRows: true,
showHeaders: true,
showTotals: false,
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/addTable.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{A0883CFE-D27E-4ECC-B94B-981830AAD55B}/tables/add',
{ address: 'A1:D4', hasHeaders: true },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,81 +1,28 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods, resource: string) {
if (method === 'GET') {
return {
value: [
{
name: 'id',
},
{
name: 'name',
},
{
name: 'age',
},
{
name: 'data',
},
],
};
}
if (method === 'POST' && resource.includes('createSession')) {
return {
id: 12345,
};
}
if (method === 'POST' && resource.includes('add')) {
return {
index: 3,
values: [[3, 'Donald', 99, 'data 5']],
};
}
if (method === 'POST' && resource.includes('closeSession')) {
return;
}
}),
};
});
describe('Test MicrosoftExcelV2, table => append', () => { describe('Test MicrosoftExcelV2, table => append', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/append.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/tables/%7B317CA469-7D1C-4A5D-9B0B-424444BF0336%7D/columns',
)
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .reply(200, {
const { result } = await executeWorkflow(testData, types); value: [{ name: 'id' }, { name: 'name' }, { name: 'age' }, { name: 'data' }],
})
const resultNodeData = getResultNodeData(result, testData); .post(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/tables/%7B317CA469-7D1C-4A5D-9B0B-424444BF0336%7D/rows/add',
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(4);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{A0883CFE-D27E-4ECC-B94B-981830AAD55B}/tables/{317CA469-7D1C-4A5D-9B0B-424444BF0336}/rows/add',
{ values: [['3', 'Donald', '99', 'data 5']] }, { values: [['3', 'Donald', '99', 'data 5']] },
{}, )
'', .reply(200, {
{ 'workbook-session-id': 12345 }, index: 3,
); values: [[3, 'Donald', 99, 'data 5']],
})
.post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/createSession')
.reply(200, { id: 12345 })
.post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/closeSession')
.reply(200);
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/append.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,56 +1,23 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'POST') {
return {
address: 'Sheet4!A1:D5',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Sam', 34, 'data 4'],
[3, 'Donald', 99, 'data 5'],
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, table => convertToRange', () => { describe('Test MicrosoftExcelV2, table => convertToRange', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/convertToRange.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/tables/%7B6321EE4A-AC21-48AD-87D9-B527637D94B3%7D/convertToRange',
)
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .reply(200, {
const { result } = await executeWorkflow(testData, types); address: 'Sheet4!A1:D5',
values: [
const resultNodeData = getResultNodeData(result, testData); ['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
resultNodeData.forEach(({ nodeName, resultData }) => { [2, 'Jon', 44, 'data 2'],
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); [3, 'Sam', 34, 'data 4'],
[3, 'Donald', 99, 'data 5'],
],
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/convertToRange.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{A0883CFE-D27E-4ECC-B94B-981830AAD55B}/tables/{6321EE4A-AC21-48AD-87D9-B527637D94B3}/convertToRange',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,47 +1,14 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'DELETE') {
return;
}
}),
};
});
describe('Test MicrosoftExcelV2, table => deleteTable', () => { describe('Test MicrosoftExcelV2, table => deleteTable', () => {
nock('https://graph.microsoft.com/v1.0/me')
.delete(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/tables/%7B92FBE3F5-3180-47EE-8549-40892C38DA7F%7D',
)
.reply(200);
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/deleteTable.workflow.json']; const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/deleteTable.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'DELETE',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{A0883CFE-D27E-4ECC-B94B-981830AAD55B}/tables/{92FBE3F5-3180-47EE-8549-40892C38DA7F}',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,61 +1,25 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequestAllItemsSkip: jest.fn(async function () {
return [
{
name: 'country',
},
{
name: 'browser',
},
{
name: 'session_duration',
},
{
name: 'visits',
},
];
}),
};
});
describe('Test MicrosoftExcelV2, table => getColumns', () => { describe('Test MicrosoftExcelV2, table => getColumns', () => {
nock('https://graph.microsoft.com/v1.0/me')
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/columns?%24top=100&%24skip=0',
)
.reply(200, {
value: [
{ name: 'country' },
{ name: 'browser' },
{ name: 'session_duration' },
{ name: 'visits' },
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/columns?%24top=100&%24skip=100',
)
.reply(200, { value: [] });
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/getColumns.workflow.json']; const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/getColumns.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledWith(
'value',
'GET',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{00000000-0001-0000-0000-000000000000}/tables/{613E8967-D581-44ED-81D3-82A01AA6A05C}/columns',
{},
{},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,85 +1,34 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'GET') {
return {
value: [
{
index: 0,
values: [['uk', 'firefox', 1, 1]],
},
{
index: 1,
values: [['us', 'chrome', 1, 12]],
},
],
};
}
}),
microsoftApiRequestAllItemsSkip: jest.fn(async function () {
return [
{
name: 'country',
},
{
name: 'browser',
},
{
name: 'session_duration',
},
{
name: 'visits',
},
];
}),
};
});
describe('Test MicrosoftExcelV2, table => getRows', () => { describe('Test MicrosoftExcelV2, table => getRows', () => {
nock('https://graph.microsoft.com/v1.0/me')
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/rows?%24top=2',
)
.reply(200, {
value: [
{ index: 0, values: [['uk', 'firefox', 1, 1]] },
{ index: 1, values: [['us', 'chrome', 1, 12]] },
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/columns?%24select=name&%24top=100&%24skip=0',
)
.reply(200, {
value: [
{ name: 'country' },
{ name: 'browser' },
{ name: 'session_duration' },
{ name: 'visits' },
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/columns?%24select=name&%24top=100&%24skip=100',
)
.reply(200, { value: [] });
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/getRows.workflow.json']; const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/getRows.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'GET',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{00000000-0001-0000-0000-000000000000}/tables/{613E8967-D581-44ED-81D3-82A01AA6A05C}/rows',
{},
{ $top: 2 },
);
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledWith(
'value',
'GET',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{00000000-0001-0000-0000-000000000000}/tables/{613E8967-D581-44ED-81D3-82A01AA6A05C}/columns',
{},
{ $select: 'name' },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,102 +1,42 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequestAllItemsSkip: jest.fn(async function (
_property: string,
_method: IHttpRequestMethods,
endpoint: string,
) {
if (endpoint.includes('columns')) {
return [
{
name: 'country',
},
{
name: 'browser',
},
{
name: 'session_duration',
},
{
name: 'visits',
},
];
}
if (endpoint.includes('rows')) {
return [
{
index: 0,
values: [['uk', 'firefox', 1, 1]],
},
{
index: 1,
values: [['us', 'chrome', 1, 12]],
},
{
index: 2,
values: [['test', 'test', 55, 123]],
},
{
index: 3,
values: [['ua', 'chrome', 1, 3]],
},
{
index: 4,
values: [['ua', 'firefox', 1, 4]],
},
{
index: 5,
values: [['uk', 'chrome', 1, 55]],
},
];
}
}),
};
});
describe('Test MicrosoftExcelV2, table => lookup', () => { describe('Test MicrosoftExcelV2, table => lookup', () => {
nock('https://graph.microsoft.com/v1.0/me')
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/rows?%24top=100&%24skip=0',
)
.reply(200, {
value: [
{ index: 0, values: [['uk', 'firefox', 1, 1]] },
{ index: 1, values: [['us', 'chrome', 1, 12]] },
{ index: 2, values: [['test', 'test', 55, 123]] },
{ index: 3, values: [['ua', 'chrome', 1, 3]] },
{ index: 4, values: [['ua', 'firefox', 1, 4]] },
{ index: 5, values: [['uk', 'chrome', 1, 55]] },
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/rows?%24top=100&%24skip=100',
)
.reply(200, { value: [] })
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/columns?%24select=name&%24top=100&%24skip=0',
)
.reply(200, {
value: [
{ name: 'country' },
{ name: 'browser' },
{ name: 'session_duration' },
{ name: 'visits' },
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/tables/%7B613E8967-D581-44ED-81D3-82A01AA6A05C%7D/columns?%24select=name&%24top=100&%24skip=100',
)
.reply(200, { value: [] });
const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/lookup.workflow.json']; const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/lookup.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledTimes(2);
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledWith(
'value',
'GET',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{00000000-0001-0000-0000-000000000000}/tables/{613E8967-D581-44ED-81D3-82A01AA6A05C}/rows',
{},
{},
);
expect(transport.microsoftApiRequestAllItemsSkip).toHaveBeenCalledWith(
'value',
'GET',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{00000000-0001-0000-0000-000000000000}/tables/{613E8967-D581-44ED-81D3-82A01AA6A05C}/columns',
{},
{ $select: 'name' },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,77 +1,26 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods, resource: string) {
if (method === 'POST' && resource.includes('createSession')) {
return {
id: 12345,
};
}
if (method === 'POST' && resource.includes('add')) {
return {
id: '{266ADAB7-25B6-4F28-A2D1-FD5BFBD7A4F0}',
name: 'Sheet42',
position: 8,
visibility: 'Visible',
};
}
if (method === 'POST' && resource.includes('closeSession')) {
return;
}
}),
};
});
describe('Test MicrosoftExcelV2, workbook => addWorksheet', () => { describe('Test MicrosoftExcelV2, workbook => addWorksheet', () => {
nock('https://graph.microsoft.com/v1.0/me')
.post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/createSession', {
persistChanges: true,
})
.reply(200, { id: 12345 })
.post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/add', {
name: 'Sheet42',
})
.matchHeader('workbook-session-id', '12345')
.reply(200, {
id: '{266ADAB7-25B6-4F28-A2D1-FD5BFBD7A4F0}',
name: 'Sheet42',
position: 8,
visibility: 'Visible',
})
.post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/closeSession')
.reply(200);
const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.workflow.json']; const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(3);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/createSession',
{ persistChanges: true },
);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/add',
{ name: 'Sheet42' },
{},
'',
{ 'workbook-session-id': 12345 },
);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/closeSession',
{},
{},
'',
{ 'workbook-session-id': 12345 },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,47 +1,12 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'DELETE') {
return;
}
}),
};
});
describe('Test MicrosoftExcelV2, workbook => deleteWorkbook', () => { describe('Test MicrosoftExcelV2, workbook => deleteWorkbook', () => {
nock('https://graph.microsoft.com/v1.0/me')
.delete('/drive/items/01FUWX3BXJLISGF2CFWBGYPHXFCXPXOJUK')
.reply(200);
const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.workflow.json']; const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'DELETE',
'/drive/items/01FUWX3BXJLISGF2CFWBGYPHXFCXPXOJUK',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,62 +1,23 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'GET') {
return {
value: [
{
'@odata.type': '#microsoft.graph.driveItem',
name: 'ПРРО копія.xlsx',
},
,
{
'@odata.type': '#microsoft.graph.driveItem',
name: 'Book 3.xlsx',
},
,
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, workbook => getAll', () => { describe('Test MicrosoftExcelV2, workbook => getAll', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/getAll.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get("/drive/root/search(q='.xlsx')?%24select=name&%24top=2")
const nodeTypes = setup(tests); .reply(200, {
value: [
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { {
const { result } = await executeWorkflow(testData, types); '@odata.type': '#microsoft.graph.driveItem',
name: 'ПРРО копія.xlsx',
const resultNodeData = getResultNodeData(result, testData); },
{
resultNodeData.forEach(({ nodeName, resultData }) => { '@odata.type': '#microsoft.graph.driveItem',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); name: 'Book 3.xlsx',
},
],
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/getAll.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'GET',
"/drive/root/search(q='.xlsx')",
{},
{ $select: 'name', $top: 2 },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,45 +1,42 @@
import type { IHttpRequestMethods } from 'n8n-workflow'; import nock from 'nock';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers'; import { testWorkflows } from '@test/nodes/Helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods, resource: string) {
if (method === 'GET' && resource.includes('usedRange')) {
return {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
};
}
if (method === 'PATCH' && resource.includes('{A0883CFE-D27E-4ECC-B94B-981830AAD55B}')) {
return {
values: [[4, 'Sam', 34, 'data 4']],
};
}
if (method === 'PATCH' && resource.includes('{426949D7-797F-43A9-A8A4-8FE283495A82}')) {
return {
values: [[4, 'Don', 37, 'data 44']],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => append', () => { describe('Test MicrosoftExcelV2, worksheet => append', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/append.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/usedRange',
)
.reply(200, {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.patch(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/range(address='A7:D7')",
)
.reply(200, { values: [[4, 'Sam', 34, 'data 4']] })
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B426949D7-797F-43A9-A8A4-8FE283495A82%7D/usedRange',
)
.reply(200, {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.patch(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B426949D7-797F-43A9-A8A4-8FE283495A82%7D/range(address='A7:D7')",
)
.reply(200, { values: [[4, 'Don', 37, 'data 44']] });
for (const testData of tests) { const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/append.workflow.json'];
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,56 +1,17 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'POST') {
return {
values: [
{
json: {
success: true,
},
},
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => clear', () => { describe('Test MicrosoftExcelV2, worksheet => clear', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/clear.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BF7AF92FE-D42D-452F-8E4A-901B1D1EBF3F%7D/range/clear',
{ applyTo: 'All' },
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { )
const { result } = await executeWorkflow(testData, types); .reply(200, {
values: [{ json: { success: true } }],
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/clear.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{F7AF92FE-D42D-452F-8E4A-901B1D1EBF3F}/range/clear',
{ applyTo: 'All' },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,55 +1,16 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'DELETE') {
return {
values: [
{
json: {
success: true,
},
},
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => deleteWorksheet', () => { describe('Test MicrosoftExcelV2, worksheet => deleteWorksheet', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .delete(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B88D9C37A-4180-4B23-8996-BF11F32EB63C%7D',
)
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .reply(200, {
const { result } = await executeWorkflow(testData, types); values: [{ json: { success: true } }],
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'DELETE',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/{88D9C37A-4180-4B23-8996-BF11F32EB63C}',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,64 +1,29 @@
import type { IHttpRequestMethods, INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'GET') {
return {
value: [
{
id: '{00000000-0001-0000-0000-000000000000}',
name: 'Sheet1',
},
{
id: '{F7AF92FE-D42D-452F-8E4A-901B1D1EBF3F}',
name: 'Sheet2',
},
{
id: '{BF7BD843-4912-4B81-A0AC-4FBBC2783E20}',
name: 'foo2',
},
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => getAll', () => { describe('Test MicrosoftExcelV2, worksheet => getAll', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets?%24select=name&%24top=3',
)
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .reply(200, {
const { result } = await executeWorkflow(testData, types); value: [
{
const resultNodeData = getResultNodeData(result, testData); id: '{00000000-0001-0000-0000-000000000000}',
name: 'Sheet1',
resultNodeData.forEach(({ nodeName, resultData }) => { },
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); {
id: '{F7AF92FE-D42D-452F-8E4A-901B1D1EBF3F}',
name: 'Sheet2',
},
{
id: '{BF7BD843-4912-4B81-A0AC-4FBBC2783E20}',
name: 'foo2',
},
],
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'GET',
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets',
{},
{ $select: 'name', $top: 3 },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,42 +1,31 @@
import type { IHttpRequestMethods } from 'n8n-workflow'; import nock from 'nock';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers'; import { testWorkflows } from '@test/nodes/Helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods, resource: string) {
{
if (method === 'GET' && resource.includes('usedRange')) {
return {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
};
}
return {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => readRows', () => { describe('Test MicrosoftExcelV2, worksheet => readRows', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/usedRange',
)
.reply(200, {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.get(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/range(address='A1:D3')",
)
.reply(200, {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
],
});
for (const testData of tests) { const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.workflow.json'];
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,55 +1,56 @@
import type { IHttpRequestMethods } from 'n8n-workflow'; import nock from 'nock';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers'; import { testWorkflows } from '@test/nodes/Helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods, resource: string) {
if (method === 'GET' && resource.includes('usedRange')) {
return {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
};
}
if (method === 'PATCH' && resource.includes('{A0883CFE-D27E-4ECC-B94B-981830AAD55B}')) {
return {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Sam', 34, 'data 4'],
],
};
}
if (method === 'PATCH' && resource.includes('{426949D7-797F-43A9-A8A4-8FE283495A82}')) {
return {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Don', 37, 'data 44'],
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => update', () => { describe('Test MicrosoftExcelV2, worksheet => update', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/update.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/usedRange',
)
.reply(200, {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.patch(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/range(address='A1:D6')",
)
.reply(200, {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Sam', 34, 'data 4'],
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B426949D7-797F-43A9-A8A4-8FE283495A82%7D/usedRange',
)
.reply(200, {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.patch(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B426949D7-797F-43A9-A8A4-8FE283495A82%7D/range(address='A1:D6')",
)
.reply(200, {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Don', 37, 'data 44'],
],
});
for (const testData of tests) { const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/update.workflow.json'];
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,57 +1,58 @@
import type { IHttpRequestMethods } from 'n8n-workflow'; import nock from 'nock';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers'; import { testWorkflows } from '@test/nodes/Helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: IHttpRequestMethods, resource: string) {
if (method === 'GET' && resource.includes('usedRange')) {
return {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
};
}
if (method === 'PATCH' && resource.includes('{A0883CFE-D27E-4ECC-B94B-981830AAD55B}')) {
return {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
[4, 'Sam', 34, 'data 4'],
],
};
}
if (method === 'PATCH' && resource.includes('{426949D7-797F-43A9-A8A4-8FE283495A82}')) {
return {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
[4, 'Don', 37, 'data 44'],
],
};
}
}),
};
});
describe('Test MicrosoftExcelV2, worksheet => upsert', () => { describe('Test MicrosoftExcelV2, worksheet => upsert', () => {
const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/usedRange',
)
.reply(200, {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.patch(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7BA0883CFE-D27E-4ECC-B94B-981830AAD55B%7D/range(address='A1:D7')",
)
.reply(200, {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
[4, 'Sam', 34, 'data 4'],
],
})
.get(
'/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B426949D7-797F-43A9-A8A4-8FE283495A82%7D/usedRange',
)
.reply(200, {
address: 'Sheet4!A1:D6',
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
],
})
.patch(
"/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/worksheets/%7B426949D7-797F-43A9-A8A4-8FE283495A82%7D/range(address='A1:D7')",
)
.reply(200, {
values: [
['id', 'name', 'age', 'data'],
[1, 'Sam', 33, 'data 1'],
[2, 'Jon', 44, 'data 2'],
[3, 'Ron', 55, 'data 3'],
[4, 'Don', 37, 'data 44'],
],
});
for (const testData of tests) { const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.workflow.json'];
test(testData.description, async () => await equalityTest(testData, nodeTypes)); testWorkflows(workflows);
}
}); });

View File

@@ -1,68 +1,35 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendarGroups('AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRu_AAA%3D')/calendars/$entity",
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAFXBBZ_AAA=',
name: 'New Calendar',
color: 'lightOrange',
hexColor: '#fcab73',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAABVtwWTA==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, calendar => create', () => { describe('Test MicrosoftOutlookV2, calendar => create', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/create.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/calendarGroups/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRu_AAA=/calendars', '/calendarGroups/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRu_AAA=/calendars',
{ color: 'lightOrange', name: 'New Calendar' }, { color: 'lightOrange', name: 'New Calendar' },
); )
.reply(200, {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendarGroups('AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRu_AAA%3D')/calendars/$entity",
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAFXBBZ_AAA=',
name: 'New Calendar',
color: 'lightOrange',
hexColor: '#fcab73',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAABVtwWTA==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/create.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,47 +1,14 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'DELETE') {
return {};
}
}),
};
});
describe('Test MicrosoftOutlookV2, calendar => delete', () => { describe('Test MicrosoftOutlookV2, calendar => delete', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/delete.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .delete(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'DELETE',
'/calendars/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvIAAA=', '/calendars/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvIAAA=',
); )
.reply(200);
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/delete.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,69 +1,34 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'GET') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendars/$entity",
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
name: 'Foo Calendar',
color: 'lightGreen',
hexColor: '#87d28e',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAAAi67hiw==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, calendar => get', () => { describe('Test MicrosoftOutlookV2, calendar => get', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/get.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .get(
const nodeTypes = setup(tests); '/calendars/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
)
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .reply(200, {
const { result } = await executeWorkflow(testData, types); '@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendars/$entity",
const resultNodeData = getResultNodeData(result, testData); id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
name: 'Foo Calendar',
resultNodeData.forEach(({ nodeName, resultData }) => { color: 'lightGreen',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); hexColor: '#87d28e',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAAAi67hiw==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/get.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'GET',
'/calendars/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
undefined,
{},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,88 +1,53 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'GET') {
return {
value: [
{
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAAJ9-JDAAA=',
name: 'Calendar',
color: 'auto',
hexColor: '',
isDefaultCalendar: true,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAAACfdHfw==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: true,
isRemovable: false,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
},
{
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvBAAA=',
name: 'Third calendar',
color: 'lightYellow',
hexColor: '#fde300',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAAAi67hIw==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
},
],
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, calendar => getAll', () => { describe('Test MicrosoftOutlookV2, calendar => getAll', () => {
nock('https://graph.microsoft.com/v1.0/me')
.get('/calendars?%24filter=canEdit%20eq%20true&%24top=2')
.reply(200, {
value: [
{
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAAJ9-JDAAA=',
name: 'Calendar',
color: 'auto',
hexColor: '',
isDefaultCalendar: true,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAAACfdHfw==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: true,
isRemovable: false,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
},
{
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvBAAA=',
name: 'Third calendar',
color: 'lightYellow',
hexColor: '#fde300',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAAAi67hIw==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
},
],
});
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.workflow.json']; const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.workflow.json'];
const tests = workflowToTests(workflows); testWorkflows(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith('GET', '/calendars', undefined, {
$filter: 'canEdit eq true',
$top: 2,
});
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,68 +1,35 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'PATCH') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendars/$entity",
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
name: 'Foo',
color: 'lightOrange',
hexColor: '#fcab73',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAABVtwYKA==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, calendar => update', () => { describe('Test MicrosoftOutlookV2, calendar => update', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/update.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .patch(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'PATCH',
'/calendars/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=', '/calendars/AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
{ color: 'lightOrange', isDefaultCalendar: false, name: 'Foo' }, { color: 'lightOrange', isDefaultCalendar: false, name: 'Foo' },
); )
.reply(200, {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendars/$entity",
id: 'AAAXXXYYYnnnT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAACLtRvGAAA=',
name: 'Foo',
color: 'lightOrange',
hexColor: '#fcab73',
isDefaultCalendar: false,
changeKey: 'WX+A3vy5K0qqTyPHso1JgAABVtwYKA==',
canShare: true,
canViewPrivateItems: true,
canEdit: true,
allowedOnlineMeetingProviders: ['teamsForBusiness'],
defaultOnlineMeetingProvider: 'teamsForBusiness',
isTallyingResponses: false,
isRemovable: true,
owner: {
name: 'User Name',
address: 'test@mail.com',
},
});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/update.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,82 +1,10 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/contacts/$entity",
'@odata.etag': 'W/"EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bob"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAABZf4De-LkrSqpPI8eyjUmAAAFXBCQuAAA=',
createdDateTime: '2023-09-04T08:48:39Z',
lastModifiedDateTime: '2023-09-04T08:48:39Z',
changeKey: 'EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bob',
categories: ['blue', 'green'],
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAAA=',
birthday: '1991-09-19T11:59:00Z',
fileAs: '',
displayName: 'User Name',
givenName: 'User',
initials: null,
middleName: null,
nickName: null,
surname: 'Name',
title: 'Title',
yomiGivenName: null,
yomiSurname: null,
yomiCompanyName: null,
generation: null,
imAddresses: [],
jobTitle: null,
companyName: 'Company',
department: 'IT',
officeLocation: null,
profession: null,
businessHomePage: null,
assistantName: 'Assistant',
manager: null,
homePhones: [],
mobilePhone: null,
businessPhones: [],
spouseName: null,
personalNotes: '',
children: [],
emailAddresses: [],
homeAddress: {},
businessAddress: {},
otherAddress: {},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, contact => create', () => { describe('Test MicrosoftOutlookV2, contact => create', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/contact/create.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post('/contacts', {
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith('POST', '/contacts', {
assistantName: 'Assistant', assistantName: 'Assistant',
birthday: '1991-09-19T21:00:00.000Z', birthday: '1991-09-19T21:00:00.000Z',
categories: ['blue', 'green'], categories: ['blue', 'green'],
@@ -86,12 +14,52 @@ describe('Test MicrosoftOutlookV2, contact => create', () => {
givenName: 'User', givenName: 'User',
surname: 'Name', surname: 'Name',
title: 'Title', title: 'Title',
})
.reply(200, {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/contacts/$entity",
'@odata.etag': 'W/"EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bob"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAABZf4De-LkrSqpPI8eyjUmAAAFXBCQuAAA=',
createdDateTime: '2023-09-04T08:48:39Z',
lastModifiedDateTime: '2023-09-04T08:48:39Z',
changeKey: 'EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bob',
categories: ['blue', 'green'],
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAAA=',
birthday: '1991-09-19T11:59:00Z',
fileAs: '',
displayName: 'User Name',
givenName: 'User',
initials: null,
middleName: null,
nickName: null,
surname: 'Name',
title: 'Title',
yomiGivenName: null,
yomiSurname: null,
yomiCompanyName: null,
generation: null,
imAddresses: [],
jobTitle: null,
companyName: 'Company',
department: 'IT',
officeLocation: null,
profession: null,
businessHomePage: null,
assistantName: 'Assistant',
manager: null,
homePhones: [],
mobilePhone: null,
businessPhones: [],
spouseName: null,
personalNotes: '',
children: [],
emailAddresses: [],
homeAddress: {},
businessAddress: {},
otherAddress: {},
}); });
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/contact/create.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,89 +1,10 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'PATCH') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/contacts/$entity",
'@odata.etag': 'W/"EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bou"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAABZf4De-LkrSqpPI8eyjUmAAAFXBCQuAAA=',
createdDateTime: '2023-09-04T08:48:39Z',
lastModifiedDateTime: '2023-09-04T09:06:21Z',
changeKey: 'EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bou',
categories: ['blue', 'green'],
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAAA=',
birthday: '1991-09-19T11:59:00Z',
fileAs: '',
displayName: 'Username',
givenName: 'User',
initials: null,
middleName: null,
nickName: null,
surname: 'Name',
title: 'Title',
yomiGivenName: null,
yomiSurname: null,
yomiCompanyName: null,
generation: null,
imAddresses: [],
jobTitle: null,
companyName: 'Company',
department: 'IT',
officeLocation: null,
profession: null,
businessHomePage: null,
assistantName: 'Assistant',
manager: 'Manager',
homePhones: [],
mobilePhone: '',
businessPhones: ['999000555777'],
spouseName: '',
personalNotes: '',
children: [],
emailAddresses: [],
homeAddress: {},
businessAddress: {
street: 'Street',
city: 'City',
state: 'State',
countryOrRegion: 'Country',
postalCode: '777777',
},
otherAddress: {},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, contact => update', () => { describe('Test MicrosoftOutlookV2, contact => update', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/contact/update.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .patch(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'PATCH',
'/contacts/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAABZf4De-LkrSqpPI8eyjUmAAAFXBCQuAAA=', '/contacts/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAABZf4De-LkrSqpPI8eyjUmAAAFXBCQuAAA=',
{ {
businessAddress: { businessAddress: {
@@ -97,12 +18,58 @@ describe('Test MicrosoftOutlookV2, contact => update', () => {
displayName: 'Username', displayName: 'Username',
manager: 'Manager', manager: 'Manager',
}, },
); )
.reply(200, {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/contacts/$entity",
'@odata.etag': 'W/"EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bou"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAABZf4De-LkrSqpPI8eyjUmAAAFXBCQuAAA=',
createdDateTime: '2023-09-04T08:48:39Z',
lastModifiedDateTime: '2023-09-04T09:06:21Z',
changeKey: 'EQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bou',
categories: ['blue', 'green'],
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEOAAA=',
birthday: '1991-09-19T11:59:00Z',
fileAs: '',
displayName: 'Username',
givenName: 'User',
initials: null,
middleName: null,
nickName: null,
surname: 'Name',
title: 'Title',
yomiGivenName: null,
yomiSurname: null,
yomiCompanyName: null,
generation: null,
imAddresses: [],
jobTitle: null,
companyName: 'Company',
department: 'IT',
officeLocation: null,
profession: null,
businessHomePage: null,
assistantName: 'Assistant',
manager: 'Manager',
homePhones: [],
mobilePhone: '',
businessPhones: ['999000555777'],
spouseName: '',
personalNotes: '',
children: [],
emailAddresses: [],
homeAddress: {},
businessAddress: {
street: 'Street',
city: 'City',
state: 'State',
countryOrRegion: 'Country',
postalCode: '777777',
},
otherAddress: {},
});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/contact/update.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,137 +1,100 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/messages/$entity",
'@odata.etag': 'W/"CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bo2"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDupAAA=',
createdDateTime: '2023-09-04T09:18:35Z',
lastModifiedDateTime: '2023-09-04T09:18:35Z',
changeKey: 'CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bo2',
categories: [
'd10cd8f9-14ac-460e-a6ec-c40dd1876ea2',
'6844a34e-4d23-4805-9fec-38b7f6e1a780',
'fbf44fcd-7689-43a0-99c8-2c9faf6d825a',
],
receivedDateTime: '2023-09-04T09:18:35Z',
sentDateTime: '2023-09-04T09:18:35Z',
hasAttachments: false,
internetMessageId:
'<AM0PR10MB21003DD359041CBE7D64DDB6DDE9A@AM0PR10MB2100.EURPRD10.PROD.OUTLOOK.COM>',
subject: 'New Draft',
bodyPreview: 'draft message',
importance: 'normal',
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAAA=',
conversationId:
'AAQkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAQAKELKTNBg5JJuTnBGaTDyl0=',
conversationIndex: 'AQHZ3xDIoQspM0GDkkm5OcEZpMPKXQ==',
isDeliveryReceiptRequested: false,
isReadReceiptRequested: true,
isRead: true,
isDraft: true,
webLink:
'https://outlook.office365.com/owa/?ItemID=AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De%2FLkrSqpPI8eyjUmAAAAAAAEPAABZf4De%2FLkrSqpPI8eyjUmAAAFXBDupAAA%3D&exvsurl=1&viewmodel=ReadMessageItem',
inferenceClassification: 'focused',
body: {
contentType: 'text',
content: 'draft message',
},
toRecipients: [
{
emailAddress: {
name: 'some@mail.com',
address: 'some@mail.com',
},
},
],
ccRecipients: [],
bccRecipients: [
{
emailAddress: {
name: 'name1@mail.com',
address: 'name1@mail.com',
},
},
{
emailAddress: {
name: 'name2@mail.com',
address: 'name2@mail.com',
},
},
],
replyTo: [
{
emailAddress: {
name: 'reply@mail.com',
address: 'reply@mail.com',
},
},
],
flag: {
flagStatus: 'notFlagged',
},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, draft => create', () => { describe('Test MicrosoftOutlookV2, draft => create', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/draft/create.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post('/messages', {
const nodeTypes = setup(tests); bccRecipients: [
{ emailAddress: { address: 'name1@mail.com' } },
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { { emailAddress: { address: 'name2@mail.com' } },
const { result } = await executeWorkflow(testData, types); ],
body: { content: 'draft message', contentType: 'Text' },
const resultNodeData = getResultNodeData(result, testData); categories: [
'd10cd8f9-14ac-460e-a6ec-c40dd1876ea2',
resultNodeData.forEach(({ nodeName, resultData }) => { '6844a34e-4d23-4805-9fec-38b7f6e1a780',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); 'fbf44fcd-7689-43a0-99c8-2c9faf6d825a',
],
importance: 'Normal',
internetMessageHeaders: [{ name: 'x-my-header', value: 'header value' }],
isReadReceiptRequested: true,
replyTo: [{ emailAddress: { address: 'reply@mail.com' } }],
subject: 'New Draft',
toRecipients: [{ emailAddress: { address: 'some@mail.com' } }],
})
.reply(200, {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/messages/$entity",
'@odata.etag': 'W/"CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bo2"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDupAAA=',
createdDateTime: '2023-09-04T09:18:35Z',
lastModifiedDateTime: '2023-09-04T09:18:35Z',
changeKey: 'CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3Bo2',
categories: [
'd10cd8f9-14ac-460e-a6ec-c40dd1876ea2',
'6844a34e-4d23-4805-9fec-38b7f6e1a780',
'fbf44fcd-7689-43a0-99c8-2c9faf6d825a',
],
receivedDateTime: '2023-09-04T09:18:35Z',
sentDateTime: '2023-09-04T09:18:35Z',
hasAttachments: false,
internetMessageId:
'<AM0PR10MB21003DD359041CBE7D64DDB6DDE9A@AM0PR10MB2100.EURPRD10.PROD.OUTLOOK.COM>',
subject: 'New Draft',
bodyPreview: 'draft message',
importance: 'normal',
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAAA=',
conversationId:
'AAQkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAQAKELKTNBg5JJuTnBGaTDyl0=',
conversationIndex: 'AQHZ3xDIoQspM0GDkkm5OcEZpMPKXQ==',
isDeliveryReceiptRequested: false,
isReadReceiptRequested: true,
isRead: true,
isDraft: true,
webLink:
'https://outlook.office365.com/owa/?ItemID=AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De%2FLkrSqpPI8eyjUmAAAAAAAEPAABZf4De%2FLkrSqpPI8eyjUmAAAFXBDupAAA%3D&exvsurl=1&viewmodel=ReadMessageItem',
inferenceClassification: 'focused',
body: {
contentType: 'text',
content: 'draft message',
},
toRecipients: [
{
emailAddress: {
name: 'some@mail.com',
address: 'some@mail.com',
},
},
],
ccRecipients: [],
bccRecipients: [
{
emailAddress: {
name: 'name1@mail.com',
address: 'name1@mail.com',
},
},
{
emailAddress: {
name: 'name2@mail.com',
address: 'name2@mail.com',
},
},
],
replyTo: [
{
emailAddress: {
name: 'reply@mail.com',
address: 'reply@mail.com',
},
},
],
flag: {
flagStatus: 'notFlagged',
},
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/draft/create.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/messages',
{
bccRecipients: [
{ emailAddress: { address: 'name1@mail.com' } },
{ emailAddress: { address: 'name2@mail.com' } },
],
body: { content: 'draft message', contentType: 'Text' },
categories: [
'd10cd8f9-14ac-460e-a6ec-c40dd1876ea2',
'6844a34e-4d23-4805-9fec-38b7f6e1a780',
'fbf44fcd-7689-43a0-99c8-2c9faf6d825a',
],
importance: 'Normal',
internetMessageHeaders: [{ name: 'x-my-header', value: 'header value' }],
isReadReceiptRequested: true,
replyTo: [{ emailAddress: { address: 'reply@mail.com' } }],
subject: 'New Draft',
toRecipients: [{ emailAddress: { address: 'some@mail.com' } }],
},
{},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,52 +1,19 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {};
}
}),
};
});
describe('Test MicrosoftOutlookV2, draft => send', () => { describe('Test MicrosoftOutlookV2, draft => send', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/draft/send.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests); '/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDupAAA=/send',
)
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { .reply(200)
const { result } = await executeWorkflow(testData, types); .patch(
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(2);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'PATCH',
'/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDupAAA=', '/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDupAAA=',
{ toRecipients: [{ emailAddress: { address: 'michael.k@radency.com' } }] }, { toRecipients: [{ emailAddress: { address: 'michael.k@radency.com' } }] },
); )
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( .reply(200);
'POST',
'/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDupAAA=/send',
);
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/draft/send.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,121 +1,10 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendars('AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAAJ9-JDAAA%3D')/events/$entity",
'@odata.etag': 'W/"WX+A3vy5K0qqTyPHso1JgAABVtwgEQ=="',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAENAABZf4De-LkrSqpPI8eyjUmAAAFXBFUSAAA=',
createdDateTime: '2023-09-04T10:12:47.1985121Z',
lastModifiedDateTime: '2023-09-04T10:12:48.2173253Z',
changeKey: 'WX+A3vy5K0qqTyPHso1JgAABVtwgEQ==',
categories: ['Yellow category', 'Orange category'],
transactionId: null,
originalStartTimeZone: 'UTC',
originalEndTimeZone: 'UTC',
iCalUId:
'040000008200E00074C5B7101A82E0080000000062DD545A18DFD90100000000000000001000000004C50947C7B42140B29018ABAB42C965',
reminderMinutesBeforeStart: 15,
isReminderOn: true,
hasAttachments: false,
subject: 'New Event',
bodyPreview:
'event description\r\n________________________________________________________________________________\r\nMicrosoft Teams meeting\r\nJoin on your computer, mobile app or room device\r\nClick here to join the meeting\r\nMeeting ID: 355 132 640 047\r\nPasscode: xgUo7v',
importance: 'normal',
sensitivity: 'personal',
isAllDay: false,
isCancelled: false,
isOrganizer: true,
responseRequested: true,
seriesMasterId: null,
showAs: 'busy',
type: 'singleInstance',
webLink:
'https://outlook.office365.com/owa/?itemid=AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De%2FLkrSqpPI8eyjUmAAAAAAAENAABZf4De%2FLkrSqpPI8eyjUmAAAFXBFUSAAA%3D&exvsurl=1&path=/calendar/item',
onlineMeetingUrl: null,
isOnlineMeeting: true,
onlineMeetingProvider: 'teamsForBusiness',
allowNewTimeProposals: true,
occurrenceId: null,
isDraft: false,
hideAttendees: true,
responseStatus: {
response: 'organizer',
time: '0001-01-01T00:00:00Z',
},
body: {
contentType: 'html',
content:
'<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n</head>\r\n<body>\r\nevent description<br>\r\n<div style="width:100%"><span style="white-space:nowrap; color:#5F5F5F; opacity:.36">________________________________________________________________________________</span>\r\n</div>\r\n<div class="me-email-text" lang="en-US" style="color:#252424; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\n<div style="margin-top:24px; margin-bottom:20px"><span style="font-size:24px; color:#252424">Microsoft Teams meeting</span>\r\n</div>\r\n<div style="margin-bottom:20px">\r\n<div style="margin-top:0px; margin-bottom:0px; font-weight:bold"><span style="font-size:14px; color:#252424">Join on your computer, mobile app or room device</span>\r\n</div>\r\n<a href="https://teams.microsoft.com/l/meetup-join/19%3ameeting_MDZmMzZmYzYtMDc4Yi00NTA2LWE3MTMtZDc5ZDI1M2JmY2M3%40thread.v2/0?context=%7b%22Tid%22%3a%2223786ca6-7ff2-4672-87d0-5c649ee0a337%22%2c%22Oid%22%3a%22b834447b-6848-4af9-8390-d2259ce46b74%22%7d" class="me-email-headline" style="font-size:14px; font-family:\'Segoe UI Semibold\',\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif; text-decoration:underline; color:#6264a7">Click\r\n here to join the meeting</a> </div>\r\n<div style="margin-bottom:20px; margin-top:20px">\r\n<div style="margin-bottom:4px"><span data-tid="meeting-code" style="font-size:14px; color:#252424">Meeting ID:\r\n<span style="font-size:16px; color:#252424">355 132 640 047</span> </span><br>\r\n<span style="font-size:14px; color:#252424">Passcode: </span><span style="font-size:16px; color:#252424">xgUo7v\r\n</span>\r\n<div style="font-size:14px"><a href="https://www.microsoft.com/en-us/microsoft-teams/download-app" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">Download\r\n Teams</a> | <a href="https://www.microsoft.com/microsoft-teams/join-a-meeting" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\nJoin on the web</a></div>\r\n</div>\r\n</div>\r\n<div style="margin-bottom:24px; margin-top:20px"><a href="https://aka.ms/JoinTeamsMeeting" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">Learn More</a>\r\n | <a href="https://teams.microsoft.com/meetingOptions/?organizerId=b834447b-6848-4af9-8390-d2259ce46b74&amp;tenantId=23786ca6-7ff2-4672-87d0-5c649ee0a337&amp;threadId=19_meeting_MDZmMzZmYzYtMDc4Yi00NTA2LWE3MTMtZDc5ZDI1M2JmY2M3@thread.v2&amp;messageId=0&amp;language=en-US" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\nMeeting options</a> </div>\r\n</div>\r\n<div style="font-size:14px; margin-bottom:4px; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\n</div>\r\n<div style="font-size:12px"></div>\r\n<div></div>\r\n<div style="width:100%"><span style="white-space:nowrap; color:#5F5F5F; opacity:.36">________________________________________________________________________________</span>\r\n</div>\r\n</body>\r\n</html>\r\n',
},
start: {
dateTime: '2023-09-05T07:26:47.0000000',
timeZone: 'UTC',
},
end: {
dateTime: '2023-09-06T07:56:47.0000000',
timeZone: 'UTC',
},
location: {
displayName: 'Microsoft Teams Meeting',
locationType: 'default',
uniqueId: 'Microsoft Teams Meeting',
uniqueIdType: 'private',
},
locations: [
{
displayName: 'Microsoft Teams Meeting',
locationType: 'default',
uniqueId: 'Microsoft Teams Meeting',
uniqueIdType: 'private',
},
],
recurrence: null,
attendees: [],
organizer: {
emailAddress: {
name: 'Michael Kret',
address: 'MichaelDevSandbox@5w1hb7.onmicrosoft.com',
},
},
onlineMeeting: {
joinUrl:
'https://teams.microsoft.com/l/meetup-join/19%3ameeting_MDZmMzZmYzYtMDc4Yi00NTA2LWE3MTMtZDc5ZDI1M2JmY2M3%40thread.v2/0?context=%7b%22Tid%22%3a%2223786ca6-7ff2-4672-87d0-5c649ee0a337%22%2c%22Oid%22%3a%22b834447b-6848-4af9-8390-d2259ce46b74%22%7d',
},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, contact => event', () => { describe('Test MicrosoftOutlookV2, contact => event', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/event/create.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/calendars/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAAJ9-JDAAA=/events', '/calendars/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAAJ9-JDAAA=/events',
{ {
body: { content: 'event description', contentType: 'html' }, body: { content: 'event description', contentType: 'html' },
@@ -134,12 +23,90 @@ describe('Test MicrosoftOutlookV2, contact => event', () => {
subject: 'New Event', subject: 'New Event',
type: 'occurrence', type: 'occurrence',
}, },
); )
.reply(200, {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/calendars('AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEGAABZf4De-LkrSqpPI8eyjUmAAAAJ9-JDAAA%3D')/events/$entity",
'@odata.etag': 'W/"WX+A3vy5K0qqTyPHso1JgAABVtwgEQ=="',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAENAABZf4De-LkrSqpPI8eyjUmAAAFXBFUSAAA=',
createdDateTime: '2023-09-04T10:12:47.1985121Z',
lastModifiedDateTime: '2023-09-04T10:12:48.2173253Z',
changeKey: 'WX+A3vy5K0qqTyPHso1JgAABVtwgEQ==',
categories: ['Yellow category', 'Orange category'],
transactionId: null,
originalStartTimeZone: 'UTC',
originalEndTimeZone: 'UTC',
iCalUId:
'040000008200E00074C5B7101A82E0080000000062DD545A18DFD90100000000000000001000000004C50947C7B42140B29018ABAB42C965',
reminderMinutesBeforeStart: 15,
isReminderOn: true,
hasAttachments: false,
subject: 'New Event',
bodyPreview:
'event description\r\n________________________________________________________________________________\r\nMicrosoft Teams meeting\r\nJoin on your computer, mobile app or room device\r\nClick here to join the meeting\r\nMeeting ID: 355 132 640 047\r\nPasscode: xgUo7v',
importance: 'normal',
sensitivity: 'personal',
isAllDay: false,
isCancelled: false,
isOrganizer: true,
responseRequested: true,
seriesMasterId: null,
showAs: 'busy',
type: 'singleInstance',
webLink:
'https://outlook.office365.com/owa/?itemid=AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De%2FLkrSqpPI8eyjUmAAAAAAAENAABZf4De%2FLkrSqpPI8eyjUmAAAFXBFUSAAA%3D&exvsurl=1&path=/calendar/item',
onlineMeetingUrl: null,
isOnlineMeeting: true,
onlineMeetingProvider: 'teamsForBusiness',
allowNewTimeProposals: true,
occurrenceId: null,
isDraft: false,
hideAttendees: true,
responseStatus: {
response: 'organizer',
time: '0001-01-01T00:00:00Z',
},
body: {
contentType: 'html',
content:
'<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n</head>\r\n<body>\r\nevent description<br>\r\n<div style="width:100%"><span style="white-space:nowrap; color:#5F5F5F; opacity:.36">________________________________________________________________________________</span>\r\n</div>\r\n<div class="me-email-text" lang="en-US" style="color:#252424; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\n<div style="margin-top:24px; margin-bottom:20px"><span style="font-size:24px; color:#252424">Microsoft Teams meeting</span>\r\n</div>\r\n<div style="margin-bottom:20px">\r\n<div style="margin-top:0px; margin-bottom:0px; font-weight:bold"><span style="font-size:14px; color:#252424">Join on your computer, mobile app or room device</span>\r\n</div>\r\n<a href="https://teams.microsoft.com/l/meetup-join/19%3ameeting_MDZmMzZmYzYtMDc4Yi00NTA2LWE3MTMtZDc5ZDI1M2JmY2M3%40thread.v2/0?context=%7b%22Tid%22%3a%2223786ca6-7ff2-4672-87d0-5c649ee0a337%22%2c%22Oid%22%3a%22b834447b-6848-4af9-8390-d2259ce46b74%22%7d" class="me-email-headline" style="font-size:14px; font-family:\'Segoe UI Semibold\',\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif; text-decoration:underline; color:#6264a7">Click\r\n here to join the meeting</a> </div>\r\n<div style="margin-bottom:20px; margin-top:20px">\r\n<div style="margin-bottom:4px"><span data-tid="meeting-code" style="font-size:14px; color:#252424">Meeting ID:\r\n<span style="font-size:16px; color:#252424">355 132 640 047</span> </span><br>\r\n<span style="font-size:14px; color:#252424">Passcode: </span><span style="font-size:16px; color:#252424">xgUo7v\r\n</span>\r\n<div style="font-size:14px"><a href="https://www.microsoft.com/en-us/microsoft-teams/download-app" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">Download\r\n Teams</a> | <a href="https://www.microsoft.com/microsoft-teams/join-a-meeting" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\nJoin on the web</a></div>\r\n</div>\r\n</div>\r\n<div style="margin-bottom:24px; margin-top:20px"><a href="https://aka.ms/JoinTeamsMeeting" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">Learn More</a>\r\n | <a href="https://teams.microsoft.com/meetingOptions/?organizerId=b834447b-6848-4af9-8390-d2259ce46b74&amp;tenantId=23786ca6-7ff2-4672-87d0-5c649ee0a337&amp;threadId=19_meeting_MDZmMzZmYzYtMDc4Yi00NTA2LWE3MTMtZDc5ZDI1M2JmY2M3@thread.v2&amp;messageId=0&amp;language=en-US" class="me-email-link" style="font-size:14px; text-decoration:underline; color:#6264a7; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\nMeeting options</a> </div>\r\n</div>\r\n<div style="font-size:14px; margin-bottom:4px; font-family:\'Segoe UI\',\'Helvetica Neue\',Helvetica,Arial,sans-serif">\r\n</div>\r\n<div style="font-size:12px"></div>\r\n<div></div>\r\n<div style="width:100%"><span style="white-space:nowrap; color:#5F5F5F; opacity:.36">________________________________________________________________________________</span>\r\n</div>\r\n</body>\r\n</html>\r\n',
},
start: {
dateTime: '2023-09-05T07:26:47.0000000',
timeZone: 'UTC',
},
end: {
dateTime: '2023-09-06T07:56:47.0000000',
timeZone: 'UTC',
},
location: {
displayName: 'Microsoft Teams Meeting',
locationType: 'default',
uniqueId: 'Microsoft Teams Meeting',
uniqueIdType: 'private',
},
locations: [
{
displayName: 'Microsoft Teams Meeting',
locationType: 'default',
uniqueId: 'Microsoft Teams Meeting',
uniqueIdType: 'private',
},
],
recurrence: null,
attendees: [],
organizer: {
emailAddress: {
name: 'Michael Kret',
address: 'MichaelDevSandbox@5w1hb7.onmicrosoft.com',
},
},
onlineMeeting: {
joinUrl:
'https://teams.microsoft.com/l/meetup-join/19%3ameeting_MDZmMzZmYzYtMDc4Yi00NTA2LWE3MTMtZDc5ZDI1M2JmY2M3%40thread.v2/0?context=%7b%22Tid%22%3a%2223786ca6-7ff2-4672-87d0-5c649ee0a337%22%2c%22Oid%22%3a%22b834447b-6848-4af9-8390-d2259ce46b74%22%7d',
},
});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/event/create.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,60 +1,27 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/mailFolders('AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEGAAA%3D')/childFolders/$entity",
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAAA=',
displayName: 'Folder 42',
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEGAAA=',
childFolderCount: 0,
unreadItemCount: 0,
totalItemCount: 0,
sizeInBytes: 0,
isHidden: false,
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, contact => folder', () => { describe('Test MicrosoftOutlookV2, contact => folder', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/folder/create.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests); '/v1.0/me/mailFolders/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEGAAA=/childFolders',
{ displayName: 'Folder 42' },
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { )
const { result } = await executeWorkflow(testData, types); .reply(200, {
'@odata.context':
const resultNodeData = getResultNodeData(result, testData); "https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/mailFolders('AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEGAAA%3D')/childFolders/$entity",
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAAA=',
resultNodeData.forEach(({ nodeName, resultData }) => { displayName: 'Folder 42',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEGAAA=',
childFolderCount: 0,
unreadItemCount: 0,
totalItemCount: 0,
sizeInBytes: 0,
isHidden: false,
}); });
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/folder/create.workflow.json'];
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/mailFolders/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEGAAA=/childFolders',
{ displayName: 'Folder 42' },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,55 +1,23 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport'; describe('Test MicrosoftOutlookV2, folderMessage => getAll', () => {
nock('https://graph.microsoft.com/v1.0/me')
jest.mock('../../../../v2/transport', () => { .get(
const originalModule = jest.requireActual('../../../../v2/transport'); '/mailFolders/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAAA=/messages?%24select=bodyPreview%2Csubject&%24top=100',
return { )
...originalModule, .reply(200, {
microsoftApiRequestAllItems: jest.fn(async function () { value: [
return [
{ {
'@odata.etag': 'W/"CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3CAj"', '@odata.etag': 'W/"CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3CAj"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAABZf4De-LkrSqpPI8eyjUmAAAFXBGDUAAA=', id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAABZf4De-LkrSqpPI8eyjUmAAAFXBGDUAAA=',
subject: 'XXXX', subject: 'XXXX',
bodyPreview: 'test', bodyPreview: 'test',
}, },
]; ],
}),
};
});
describe('Test MicrosoftOutlookV2, folderMessage => getAll', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(transport.microsoftApiRequestAllItems).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.workflow.json'];
expect(transport.microsoftApiRequestAllItems).toHaveBeenCalledWith( testWorkflows(workflows);
'value',
'GET',
'/mailFolders/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAAA=/messages',
undefined,
{ $select: 'bodyPreview,subject' },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,51 +1,18 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {};
}
}),
};
});
describe('Test MicrosoftOutlookV2, message => move', () => { describe('Test MicrosoftOutlookV2, message => move', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/move.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEJAABZf4De-LkrSqpPI8eyjUmAAAFXBEVwAAA=/move', '/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEJAABZf4De-LkrSqpPI8eyjUmAAAFXBEVwAAA=/move',
{ {
destinationId: destinationId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAAA=', 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAFXBAEHAAA=',
}, },
); )
.reply(200);
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/move.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,100 +1,10 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {
'@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/messages/$entity",
'@odata.etag': 'W/"CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3CX+"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDurAAA=',
createdDateTime: '2023-09-04T12:29:59Z',
lastModifiedDateTime: '2023-09-04T12:29:59Z',
changeKey: 'CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3CX+',
categories: [],
receivedDateTime: '2023-09-04T12:29:59Z',
sentDateTime: '2023-09-04T12:29:59Z',
hasAttachments: false,
internetMessageId:
'<AM0PR10MB2100903A148F1623165004E3DDE9A@AM0PR10MB2100.EURPRD10.PROD.OUTLOOK.COM>',
subject: 'Reply Subject',
bodyPreview: 'Reply message',
importance: 'high',
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAAA=',
conversationId:
'AAQkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAQAKwkQLinj69KtoFOxMG2lVY=',
conversationIndex: 'AQHZ3yq3rCRAuKePr0q2gU7EwbaVVrAKmLQ4',
isDeliveryReceiptRequested: false,
isReadReceiptRequested: false,
isRead: true,
isDraft: true,
webLink:
'https://outlook.office365.com/owa/?ItemID=AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De%2FLkrSqpPI8eyjUmAAAAAAAEPAABZf4De%2FLkrSqpPI8eyjUmAAAFXBDurAAA%3D&exvsurl=1&viewmodel=ReadMessageItem',
inferenceClassification: 'focused',
body: {
contentType: 'html',
content:
'<html><head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>Reply message </body></html>',
},
sender: {
emailAddress: {
name: 'Michael Kret',
address: 'MichaelDevSandbox@5w1hb7.onmicrosoft.com',
},
},
from: {
emailAddress: {
name: 'Michael Kret',
address: 'MichaelDevSandbox@5w1hb7.onmicrosoft.com',
},
},
toRecipients: [
{
emailAddress: {
name: 'reply@mail.com',
address: 'reply@mail.com',
},
},
],
ccRecipients: [],
bccRecipients: [],
replyTo: [],
flag: {
flagStatus: 'notFlagged',
},
};
}
}),
};
});
describe('Test MicrosoftOutlookV2, message => reply', () => { describe('Test MicrosoftOutlookV2, message => reply', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/reply.workflow.json']; nock('https://graph.microsoft.com/v1.0/me')
const tests = workflowToTests(workflows); .post(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(2);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEJAABZf4De-LkrSqpPI8eyjUmAAAFXBEVwAAA=/createReply', '/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEJAABZf4De-LkrSqpPI8eyjUmAAAFXBEVwAAA=/createReply',
{ {
message: { message: {
@@ -103,16 +13,73 @@ describe('Test MicrosoftOutlookV2, message => reply', () => {
subject: 'Reply Subject', subject: 'Reply Subject',
}, },
}, },
); )
expect(transport.microsoftApiRequest).toHaveBeenCalledWith( .reply(200, {
'POST', '@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#users('b834447b-6848-4af9-8390-d2259ce46b74')/messages/$entity",
'@odata.etag': 'W/"CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3CX+"',
id: 'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDurAAA=',
createdDateTime: '2023-09-04T12:29:59Z',
lastModifiedDateTime: '2023-09-04T12:29:59Z',
changeKey: 'CQAAABYAAABZf4De/LkrSqpPI8eyjUmAAAFW3CX+',
categories: [],
receivedDateTime: '2023-09-04T12:29:59Z',
sentDateTime: '2023-09-04T12:29:59Z',
hasAttachments: false,
internetMessageId:
'<AM0PR10MB2100903A148F1623165004E3DDE9A@AM0PR10MB2100.EURPRD10.PROD.OUTLOOK.COM>',
subject: 'Reply Subject',
bodyPreview: 'Reply message',
importance: 'high',
parentFolderId:
'AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAuAAAAAABPLqzvT6b9RLP0CKzHiJrRAQBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAAA=',
conversationId:
'AAQkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OAAQAKwkQLinj69KtoFOxMG2lVY=',
conversationIndex: 'AQHZ3yq3rCRAuKePr0q2gU7EwbaVVrAKmLQ4',
isDeliveryReceiptRequested: false,
isReadReceiptRequested: false,
isRead: true,
isDraft: true,
webLink:
'https://outlook.office365.com/owa/?ItemID=AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De%2FLkrSqpPI8eyjUmAAAAAAAEPAABZf4De%2FLkrSqpPI8eyjUmAAAFXBDurAAA%3D&exvsurl=1&viewmodel=ReadMessageItem',
inferenceClassification: 'focused',
body: {
contentType: 'html',
content:
'<html><head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>Reply message </body></html>',
},
sender: {
emailAddress: {
name: 'Michael Kret',
address: 'MichaelDevSandbox@5w1hb7.onmicrosoft.com',
},
},
from: {
emailAddress: {
name: 'Michael Kret',
address: 'MichaelDevSandbox@5w1hb7.onmicrosoft.com',
},
},
toRecipients: [
{
emailAddress: {
name: 'reply@mail.com',
address: 'reply@mail.com',
},
},
],
ccRecipients: [],
bccRecipients: [],
replyTo: [],
flag: {
flagStatus: 'notFlagged',
},
})
.post(
'/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDurAAA=/send', '/messages/AAMkADlhOTA0MTc5LWUwOTMtNDRkZS05NzE0LTNlYmI0ZWM5OWI5OABGAAAAAABPLqzvT6b9RLP0CKzHiJrRBwBZf4De-LkrSqpPI8eyjUmAAAAAAAEPAABZf4De-LkrSqpPI8eyjUmAAAFXBDurAAA=/send',
); )
.reply(200);
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/reply.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,57 +1,20 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
microsoftApiRequest: jest.fn(async function (method: string) {
if (method === 'POST') {
return {};
}
}),
};
});
describe('Test MicrosoftOutlookV2, message => send', () => { describe('Test MicrosoftOutlookV2, message => send', () => {
const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/send.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .post('/v1.0/me/sendMail', {
const nodeTypes = setup(tests); message: {
body: { content: 'message description', contentType: 'Text' },
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { replyTo: [{ emailAddress: { address: 'reply@mail.com' } }],
const { result } = await executeWorkflow(testData, types); subject: 'Hello',
toRecipients: [{ emailAddress: { address: 'to@mail.com' } }],
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(transport.microsoftApiRequest).toHaveBeenCalledTimes(1);
expect(transport.microsoftApiRequest).toHaveBeenCalledWith(
'POST',
'/sendMail',
{
message: {
body: { content: 'message description', contentType: 'Text' },
replyTo: [{ emailAddress: { address: 'reply@mail.com' } }],
subject: 'Hello',
toRecipients: [{ emailAddress: { address: 'to@mail.com' } }],
},
saveToSentItems: true,
}, },
{}, saveToSentItems: true,
); })
.reply(200, {});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/send.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_create.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_create.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should create blob', () => { describe('should create blob', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -66,7 +55,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_delete.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_delete.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should delete blob', () => { describe('should delete blob', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -35,7 +24,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_get.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_get.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should get blob', () => { describe('should get blob', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -87,7 +76,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_getAll.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_getAll.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should get all blobs', () => { describe('should get all blobs', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -36,7 +25,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,6 +1,4 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = [ const workflows = [
@@ -8,16 +6,7 @@ describe('Azure Storage Node', () => {
]; ];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should get all blobs with limit and options', () => { describe('should get all blobs with limit and options', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -31,7 +20,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/container_create.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/container_create.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should create container', () => { describe('should create container', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -38,7 +27,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/container_delete.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/container_delete.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should delete container', () => { describe('should delete container', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -35,7 +24,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/container_get.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/container_get.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should get container', () => { describe('should get container', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -44,7 +33,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,21 +1,10 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/container_getAll.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/container_getAll.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should get all containers', () => { describe('should get all containers', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -36,7 +25,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,6 +1,4 @@
import nock from 'nock'; import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { equalityTest, setup, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = [ const workflows = [
@@ -8,16 +6,7 @@ describe('Azure Storage Node', () => {
]; ];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should get all containers with limit and options', () => { describe('should get all containers with limit and options', () => {
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -31,7 +20,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -3,25 +3,16 @@ import type {
IDataObject, IDataObject,
IHttpRequestOptions, IHttpRequestOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
import nock from 'nock';
import { CredentialsHelper, equalityTest, setup, workflowToTests } from '@test/nodes/Helpers'; import { CredentialsHelper } from '@test/nodes/credentials-helper';
import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const workflows = ['nodes/Microsoft/Storage/test/workflows/credentials_oauth2.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/credentials_oauth2.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should use correct oauth2 credentials', () => { describe('should use correct oauth2 credentials', () => {
beforeAll(() => { beforeAll(() => {
nock.disableNetConnect();
jest jest
.spyOn(CredentialsHelper.prototype, 'authenticate') .spyOn(CredentialsHelper.prototype, 'authenticate')
.mockImplementation( .mockImplementation(
@@ -45,12 +36,9 @@ describe('Azure Storage Node', () => {
}); });
afterAll(() => { afterAll(() => {
nock.restore();
jest.restoreAllMocks(); jest.restoreAllMocks();
}); });
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl: 'https://myaccount.blob.core.windows.net',
@@ -59,7 +47,6 @@ describe('Azure Storage Node', () => {
method: 'get', method: 'get',
path: '/mycontainer?restype=container', path: '/mycontainer?restype=container',
statusCode: 200, statusCode: 200,
requestHeaders: { authorization: 'bearer ACCESSTOKEN' },
responseBody: '', responseBody: '',
responseHeaders: { responseHeaders: {
'content-length': '0', 'content-length': '0',
@@ -80,7 +67,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
}); });

View File

@@ -1,26 +1,18 @@
import type { ICredentialDataDecryptedObject, IHttpRequestOptions } from 'n8n-workflow'; import type { ICredentialDataDecryptedObject, IHttpRequestOptions } from 'n8n-workflow';
import nock from 'nock';
import { CredentialsHelper, equalityTest, setup, workflowToTests } from '@test/nodes/Helpers'; import { CredentialsHelper } from '@test/nodes/credentials-helper';
import { FAKE_CREDENTIALS_DATA } from '@test/nodes/FakeCredentialsMap';
import { equalityTest, workflowToTests } from '@test/nodes/Helpers';
import { AzureStorageSharedKeyApi } from '../../../../../credentials/AzureStorageSharedKeyApi.credentials'; import { AzureStorageSharedKeyApi } from '../../../../../credentials/AzureStorageSharedKeyApi.credentials';
import { FAKE_CREDENTIALS_DATA } from '../../../../../test/nodes/FakeCredentialsMap';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
const { account, baseUrl, key } = FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi;
const workflows = ['nodes/Microsoft/Storage/test/workflows/credentials_sharedKey.workflow.json']; const workflows = ['nodes/Microsoft/Storage/test/workflows/credentials_sharedKey.workflow.json'];
const workflowTests = workflowToTests(workflows); const workflowTests = workflowToTests(workflows);
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('should use correct shared key credentials', () => { describe('should use correct shared key credentials', () => {
beforeAll(() => { beforeAll(() => {
nock.disableNetConnect();
jest jest
.spyOn(CredentialsHelper.prototype, 'authenticate') .spyOn(CredentialsHelper.prototype, 'authenticate')
.mockImplementation( .mockImplementation(
@@ -45,24 +37,17 @@ describe('Azure Storage Node', () => {
}); });
afterAll(() => { afterAll(() => {
nock.restore();
jest.restoreAllMocks(); jest.restoreAllMocks();
}); });
const nodeTypes = setup(workflowTests);
for (const workflow of workflowTests) { for (const workflow of workflowTests) {
workflow.nock = { workflow.nock = {
baseUrl: 'https://myaccount.blob.core.windows.net', baseUrl,
mocks: [ mocks: [
{ {
method: 'get', method: 'get',
path: '/mycontainer?restype=container', path: '/mycontainer?restype=container',
statusCode: 200, statusCode: 200,
requestHeaders: {
authorization:
'SharedKey Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==',
},
responseBody: '', responseBody: '',
responseHeaders: { responseHeaders: {
'content-length': '0', 'content-length': '0',
@@ -83,7 +68,7 @@ describe('Azure Storage Node', () => {
}, },
], ],
}; };
test(workflow.description, async () => await equalityTest(workflow, nodeTypes)); test(workflow.description, async () => await equalityTest(workflow));
} }
}); });
@@ -92,11 +77,11 @@ describe('Azure Storage Node', () => {
it('should remove undefined query parameters and headers', async () => { it('should remove undefined query parameters and headers', async () => {
const credentials: ICredentialDataDecryptedObject = { const credentials: ICredentialDataDecryptedObject = {
account: FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.account, account,
key: FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.key, key,
}; };
const requestOptions: IHttpRequestOptions = { const requestOptions: IHttpRequestOptions = {
url: `${FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.baseUrl}/mycontainer`, url: `${baseUrl}/mycontainer`,
qs: { restype: 'container', query1: undefined }, qs: { restype: 'container', query1: undefined },
headers: { headers: {
'Content-Length': undefined, 'Content-Length': undefined,
@@ -112,11 +97,11 @@ describe('Azure Storage Node', () => {
it('should default method to GET if not provided', async () => { it('should default method to GET if not provided', async () => {
const credentials: ICredentialDataDecryptedObject = { const credentials: ICredentialDataDecryptedObject = {
account: FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.account, account,
key: FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.key, key,
}; };
const requestOptions: IHttpRequestOptions = { const requestOptions: IHttpRequestOptions = {
url: `${FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.baseUrl}/mycontainer`, url: `${baseUrl}/mycontainer`,
qs: { restype: 'container' }, qs: { restype: 'container' },
headers: { headers: {
'Content-Length': undefined, 'Content-Length': undefined,
@@ -129,11 +114,11 @@ describe('Azure Storage Node', () => {
it('should generate a valid authorization header', async () => { it('should generate a valid authorization header', async () => {
const credentials: ICredentialDataDecryptedObject = { const credentials: ICredentialDataDecryptedObject = {
account: FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.account, account,
key: FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.key, key,
}; };
const requestOptions: IHttpRequestOptions = { const requestOptions: IHttpRequestOptions = {
url: `${FAKE_CREDENTIALS_DATA.azureStorageSharedKeyApi.baseUrl}/mycontainer/myblob`, url: `${baseUrl}/mycontainer/myblob`,
qs: { param1: 'value1' }, qs: { param1: 'value1' },
headers: { headers: {
'x-ms-date': 'Thu, 27 Feb 2025 11:05:49 GMT', 'x-ms-date': 'Thu, 27 Feb 2025 11:05:49 GMT',

View File

@@ -1,18 +1,11 @@
import type { ILoadOptionsFunctions, INodeParameterResourceLocator } from 'n8n-workflow'; import type { ILoadOptionsFunctions, INodeParameterResourceLocator } from 'n8n-workflow';
import nock from 'nock';
import { FAKE_CREDENTIALS_DATA } from '../../../../../test/nodes/FakeCredentialsMap'; import { FAKE_CREDENTIALS_DATA } from '@test/nodes/FakeCredentialsMap';
import { AzureStorage } from '../../AzureStorage.node'; import { AzureStorage } from '../../AzureStorage.node';
import { XMsVersion } from '../../GenericFunctions'; import { XMsVersion } from '../../GenericFunctions';
describe('Azure Storage Node', () => { describe('Azure Storage Node', () => {
beforeEach(() => {
// https://github.com/nock/nock/issues/2057#issuecomment-663665683
if (!nock.isActive()) {
nock.activate();
}
});
describe('List search', () => { describe('List search', () => {
it('should list search blobs', async () => { it('should list search blobs', async () => {
const mockResponse = const mockResponse =

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport'; describe('Test MicrosoftTeamsV2, channel => create', () => {
nock('https://graph.microsoft.com')
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest'); .post('/v1.0/teams/1644e7fe-547e-4223-a24f-922395865343/channels')
.reply(200, {
microsoftApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'POST') {
return {
'@odata.context': '@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#teams('1644e7fe-547e-4223-a24f-922395865343')/channels/$entity", "https://graph.microsoft.com/v1.0/$metadata#teams('1644e7fe-547e-4223-a24f-922395865343')/channels/$entity",
id: '19:16259efabba44a66916d91dd91862a6f@thread.tacv2', id: '19:16259efabba44a66916d91dd91862a6f@thread.tacv2',
@@ -22,39 +17,8 @@ microsoftApiRequestSpy.mockImplementation(async (method: string) => {
webUrl: webUrl:
'https://teams.microsoft.com/l/channel/19%3a16259efabba44a66916d91dd91862a6f%40thread.tacv2/New+Channel?groupId=1644e7fe-547e-4223-a24f-922395865343&tenantId=tenantId-111-222-333', 'https://teams.microsoft.com/l/channel/19%3a16259efabba44a66916d91dd91862a6f%40thread.tacv2/New+Channel?groupId=1644e7fe-547e-4223-a24f-922395865343&tenantId=tenantId-111-222-333',
membershipType: 'private', membershipType: 'private',
};
}
});
describe('Test MicrosoftTeamsV2, channel => create', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/create.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/create.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/v1.0/teams/1644e7fe-547e-4223-a24f-922395865343/channels',
{
description: 'new channel description',
displayName: 'New Channel',
membershipType: 'private',
},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,43 +1,14 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest');
microsoftApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'DELETE') {
return {};
}
});
describe('Test MicrosoftTeamsV2, channel => deleteChannel', () => { describe('Test MicrosoftTeamsV2, channel => deleteChannel', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .delete(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1);
expect(microsoftApiRequestSpy).toHaveBeenCalledWith(
'DELETE',
'/v1.0/teams/1644e7fe-547e-4223-a24f-922395865343/channels/19:16259efabba44a66916d91dd91862a6f@thread.tacv2', '/v1.0/teams/1644e7fe-547e-4223-a24f-922395865343/channels/19:16259efabba44a66916d91dd91862a6f@thread.tacv2',
); )
.reply(200, {});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,13 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport'; describe('Test MicrosoftTeamsV2, channel => get', () => {
nock('https://graph.microsoft.com')
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest'); .get(
'/v1.0/teams/e25bae35-7bcc-4fb7-b4f2-0d5caef251fd/channels/19:dff84a49e5124cc89dff0192c621ea0f@thread.tacv2',
microsoftApiRequestSpy.mockImplementation(async (method: string) => { )
if (method === 'GET') { .reply(200, {
return {
'@odata.context': '@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#teams('e25bae35-7bcc-4fb7-b4f2-0d5caef251fd')/channels/$entity", "https://graph.microsoft.com/v1.0/$metadata#teams('e25bae35-7bcc-4fb7-b4f2-0d5caef251fd')/channels/$entity",
id: '19:dff84a49e5124cc89dff0192c621ea0f@thread.tacv2', id: '19:dff84a49e5124cc89dff0192c621ea0f@thread.tacv2',
@@ -23,34 +20,8 @@ microsoftApiRequestSpy.mockImplementation(async (method: string) => {
webUrl: webUrl:
'https://teams.microsoft.com/l/channel/19%3Adff84a49e5124cc89dff0192c621ea0f%40thread.tacv2/General?groupId=e25bae35-7bcc-4fb7-b4f2-0d5caef251fd&tenantId=tenantId-111-222-333&allowXTenantAccess=True', 'https://teams.microsoft.com/l/channel/19%3Adff84a49e5124cc89dff0192c621ea0f%40thread.tacv2/General?groupId=e25bae35-7bcc-4fb7-b4f2-0d5caef251fd&tenantId=tenantId-111-222-333&allowXTenantAccess=True',
membershipType: 'standard', membershipType: 'standard',
};
}
});
describe('Test MicrosoftTeamsV2, channel => get', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/get.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/get.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'GET',
'/v1.0/teams/e25bae35-7bcc-4fb7-b4f2-0d5caef251fd/channels/19:dff84a49e5124cc89dff0192c621ea0f@thread.tacv2',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,82 +1,51 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequestAllItems');
microsoftApiRequestSpy.mockImplementation(async (_, method: string) => {
if (method === 'GET') {
return [
{
id: '42:aaabbbccc.tacv2',
createdDateTime: '2022-03-26T17:18:33Z',
displayName: 'Sales West',
description: 'Description of Sales West',
isFavoriteByDefault: null,
email: null,
tenantId: 'tenantId-111-222-333',
webUrl:
'https://teams.microsoft.com/l/channel/threadId/Sales%20West?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&allowXTenantAccess=False',
membershipType: 'standard',
},
{
id: '19:8662cdf2d8ff49eabdcf6364bc0fe3a2@thread.tacv2',
createdDateTime: '2022-03-26T17:18:30Z',
displayName: 'Sales East',
description: 'Description of Sales West',
isFavoriteByDefault: null,
email: null,
tenantId: 'tenantId-111-222-333',
webUrl:
'https://teams.microsoft.com/l/channel/19%3A8662cdf2d8ff49eabdcf6364bc0fe3a2%40thread.tacv2/Sales%20East?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&allowXTenantAccess=False',
membershipType: 'standard',
},
{
id: '19:a95209ede91f4d5595ac944aeb172124@thread.tacv2',
createdDateTime: '2022-03-26T17:18:16Z',
displayName: 'General',
description: 'Description of U.S. Sales',
isFavoriteByDefault: null,
email: 'U.S.Sales@5w1hb7.onmicrosoft.com',
tenantId: 'tenantId-111-222-333',
webUrl:
'https://teams.microsoft.com/l/channel/19%3Aa95209ede91f4d5595ac944aeb172124%40thread.tacv2/U.S.%20Sales?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&allowXTenantAccess=False',
membershipType: 'standard',
},
];
}
});
describe('Test MicrosoftTeamsV2, channel => getAll', () => { describe('Test MicrosoftTeamsV2, channel => getAll', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/getAll.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .get('/v1.0/teams/1111-2222-3333/channels')
const nodeTypes = setup(tests); .reply(200, {
value: [
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { {
const { result } = await executeWorkflow(testData, types); id: '42:aaabbbccc.tacv2',
createdDateTime: '2022-03-26T17:18:33Z',
const resultNodeData = getResultNodeData(result, testData); displayName: 'Sales West',
description: 'Description of Sales West',
resultNodeData.forEach(({ nodeName, resultData }) => { isFavoriteByDefault: null,
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); email: null,
tenantId: 'tenantId-111-222-333',
webUrl:
'https://teams.microsoft.com/l/channel/threadId/Sales%20West?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&allowXTenantAccess=False',
membershipType: 'standard',
},
{
id: '19:8662cdf2d8ff49eabdcf6364bc0fe3a2@thread.tacv2',
createdDateTime: '2022-03-26T17:18:30Z',
displayName: 'Sales East',
description: 'Description of Sales West',
isFavoriteByDefault: null,
email: null,
tenantId: 'tenantId-111-222-333',
webUrl:
'https://teams.microsoft.com/l/channel/19%3A8662cdf2d8ff49eabdcf6364bc0fe3a2%40thread.tacv2/Sales%20East?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&allowXTenantAccess=False',
membershipType: 'standard',
},
{
id: '19:a95209ede91f4d5595ac944aeb172124@thread.tacv2',
createdDateTime: '2022-03-26T17:18:16Z',
displayName: 'General',
description: 'Description of U.S. Sales',
isFavoriteByDefault: null,
email: 'U.S.Sales@5w1hb7.onmicrosoft.com',
tenantId: 'tenantId-111-222-333',
webUrl:
'https://teams.microsoft.com/l/channel/19%3Aa95209ede91f4d5595ac944aeb172124%40thread.tacv2/U.S.%20Sales?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&allowXTenantAccess=False',
membershipType: 'standard',
},
],
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/getAll.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'value',
'GET',
'/v1.0/teams/1111-2222-3333/channels',
{},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,44 +1,15 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest');
microsoftApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'PATCH') {
return {};
}
});
describe('Test MicrosoftTeamsV2, channel => update', () => { describe('Test MicrosoftTeamsV2, channel => update', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/update.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .patch(
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1);
expect(microsoftApiRequestSpy).toHaveBeenCalledWith(
'PATCH',
'/v1.0/teams/e25bae35-7bcc-4fb7-b4f2-0d5caef251fd/channels/19:b9daa3647ff8450bacaf39490d3e05e2@thread.tacv2', '/v1.0/teams/e25bae35-7bcc-4fb7-b4f2-0d5caef251fd/channels/19:b9daa3647ff8450bacaf39490d3e05e2@thread.tacv2',
{ description: 'new channel description', displayName: 'New Deals' }, { description: 'new channel description', displayName: 'New Deals' },
); )
.reply(200, {});
expect(result.finished).toEqual(true); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/update.workflow.json'];
}; testWorkflows(workflows);
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,13 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport'; describe('Test MicrosoftTeamsV2, channelMessage => create', () => {
nock('https://graph.microsoft.com')
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest'); .post('/beta/teams/1111-2222-3333/channels/42:aaabbbccc.tacv2/messages', {
body: { content: 'new sale', contentType: 'html' },
microsoftApiRequestSpy.mockImplementation(async (method: string) => { })
if (method === 'POST') { .reply(200, {
return {
'@odata.context': '@odata.context':
"https://graph.microsoft.com/beta/$metadata#teams('1111-2222-3333')/channels('threadId')/messages/$entity", "https://graph.microsoft.com/beta/$metadata#teams('1111-2222-3333')/channels('threadId')/messages/$entity",
id: '1698324478896', id: '1698324478896',
@@ -52,35 +49,8 @@ microsoftApiRequestSpy.mockImplementation(async (method: string) => {
attachments: [], attachments: [],
mentions: [], mentions: [],
reactions: [], reactions: [],
};
}
});
describe('Test MicrosoftTeamsV2, channelMessage => create', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channelMessage/create.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channelMessage/create.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/beta/teams/1111-2222-3333/channels/42:aaabbbccc.tacv2/messages',
{ body: { content: 'new sale', contentType: 'html' } },
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,98 +1,68 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequestAllItems');
microsoftApiRequestSpy.mockImplementation(async (_, method: string) => {
if (method === 'GET') {
return [
{
id: '1698130964682',
replyToId: null,
etag: '1698130964682',
messageType: 'message',
createdDateTime: '2023-10-24T07:02:44.682Z',
lastModifiedDateTime: '2023-10-24T07:02:44.682Z',
lastEditedDateTime: null,
deletedDateTime: null,
subject: '',
summary: null,
chatId: null,
importance: 'normal',
locale: 'en-us',
webUrl:
'https://teams.microsoft.com/l/message/threadId/1698130964682?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&createdTime=1698130964682&parentMessageId=1698130964682',
onBehalfOf: null,
policyViolation: null,
eventDetail: null,
from: {
application: null,
device: null,
user: {
'@odata.type': '#microsoft.graph.teamworkUserIdentity',
id: '11111-2222-3333',
displayName: 'My Name',
userIdentityType: 'aadUser',
tenantId: 'tenantId-111-222-333',
},
},
body: {
contentType: 'html',
content:
'<div>I added a tab at the top of this channel. Check it out!</div><attachment id="tab::f22a0494-6f7c-4512-85c5-e4ce72ce142a"></attachment>',
},
channelIdentity: {
teamId: '1111-2222-3333',
channelId: '42:aaabbbccc.tacv2',
},
attachments: [
{
id: 'tab::f22a0494-6f7c-4512-85c5-e4ce72ce142a',
contentType: 'tabReference',
contentUrl: null,
content: null,
name: 'Tasks',
thumbnailUrl: null,
teamsAppId: null,
},
],
mentions: [],
reactions: [],
},
];
}
});
describe('Test MicrosoftTeamsV2, channelMessage => getAll', () => { describe('Test MicrosoftTeamsV2, channelMessage => getAll', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .get('/beta/teams/1111-2222-3333/channels/42:aaabbbccc.tacv2/messages')
const nodeTypes = setup(tests); .reply(200, {
value: [
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { {
const { result } = await executeWorkflow(testData, types); id: '1698130964682',
replyToId: null,
const resultNodeData = getResultNodeData(result, testData); etag: '1698130964682',
messageType: 'message',
resultNodeData.forEach(({ nodeName, resultData }) => { createdDateTime: '2023-10-24T07:02:44.682Z',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); lastModifiedDateTime: '2023-10-24T07:02:44.682Z',
lastEditedDateTime: null,
deletedDateTime: null,
subject: '',
summary: null,
chatId: null,
importance: 'normal',
locale: 'en-us',
webUrl:
'https://teams.microsoft.com/l/message/threadId/1698130964682?groupId=1111-2222-3333&tenantId=tenantId-111-222-333&createdTime=1698130964682&parentMessageId=1698130964682',
onBehalfOf: null,
policyViolation: null,
eventDetail: null,
from: {
application: null,
device: null,
user: {
'@odata.type': '#microsoft.graph.teamworkUserIdentity',
id: '11111-2222-3333',
displayName: 'My Name',
userIdentityType: 'aadUser',
tenantId: 'tenantId-111-222-333',
},
},
body: {
contentType: 'html',
content:
'<div>I added a tab at the top of this channel. Check it out!</div><attachment id="tab::f22a0494-6f7c-4512-85c5-e4ce72ce142a"></attachment>',
},
channelIdentity: {
teamId: '1111-2222-3333',
channelId: '42:aaabbbccc.tacv2',
},
attachments: [
{
id: 'tab::f22a0494-6f7c-4512-85c5-e4ce72ce142a',
contentType: 'tabReference',
contentUrl: null,
content: null,
name: 'Tasks',
thumbnailUrl: null,
teamsAppId: null,
},
],
mentions: [],
reactions: [],
},
],
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'value',
'GET',
'/beta/teams/1111-2222-3333/channels/42:aaabbbccc.tacv2/messages',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport'; describe('Test MicrosoftTeamsV2, chatMessage => create', () => {
nock('https://graph.microsoft.com')
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest'); .post('/v1.0/chats/19:ebed9ad42c904d6c83adf0db360053ec@thread.v2/messages')
.reply(200, {
microsoftApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'POST') {
return {
'@odata.context': '@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#chats('19%3Aebed9ad42c904d6c83adf0db360053ec%40thread.v2')/messages/$entity", "https://graph.microsoft.com/v1.0/$metadata#chats('19%3Aebed9ad42c904d6c83adf0db360053ec%40thread.v2')/messages/$entity",
id: '1698378560692', id: '1698378560692',
@@ -48,35 +43,8 @@ microsoftApiRequestSpy.mockImplementation(async (method: string) => {
attachments: [], attachments: [],
mentions: [], mentions: [],
reactions: [], reactions: [],
};
}
});
describe('Test MicrosoftTeamsV2, chatMessage => create', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/create.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/create.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'POST',
'/v1.0/chats/19:ebed9ad42c904d6c83adf0db360053ec@thread.v2/messages',
expect.anything(),
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,16 +1,11 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport'; describe('Test MicrosoftTeamsV2, chatMessage => get', () => {
nock('https://graph.microsoft.com')
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequest'); .get('/v1.0/chats/19:ebed9ad42c904d6c83adf0db360053ec@thread.v2/messages/1698378560692')
.reply(200, {
microsoftApiRequestSpy.mockImplementation(async (method: string) => {
if (method === 'GET') {
return {
'@odata.context': '@odata.context':
"https://graph.microsoft.com/v1.0/$metadata#chats('19%3Aebed9ad42c904d6c83adf0db360053ec%40thread.v2')/messages/$entity", "https://graph.microsoft.com/v1.0/$metadata#chats('19%3Aebed9ad42c904d6c83adf0db360053ec%40thread.v2')/messages/$entity",
id: '1698378560692', id: '1698378560692',
@@ -49,34 +44,8 @@ microsoftApiRequestSpy.mockImplementation(async (method: string) => {
attachments: [], attachments: [],
mentions: [], mentions: [],
reactions: [], reactions: [],
};
}
});
describe('Test MicrosoftTeamsV2, chatMessage => get', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/get.workflow.json'];
const tests = workflowToTests(workflows);
const nodeTypes = setup(tests);
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);
const resultNodeData = getResultNodeData(result, testData);
resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/get.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'GET',
'/v1.0/chats/19:ebed9ad42c904d6c83adf0db360053ec@thread.v2/messages/1698378560692',
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

View File

@@ -1,122 +1,91 @@
import type { INodeTypes } from 'n8n-workflow'; import nock from 'nock';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; import { testWorkflows } from '@test/nodes/Helpers';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import * as transport from '../../../../v2/transport';
const microsoftApiRequestSpy = jest.spyOn(transport, 'microsoftApiRequestAllItems');
microsoftApiRequestSpy.mockImplementation(async (_, method: string) => {
if (method === 'GET') {
return [
{
id: '1698378560692',
replyToId: null,
etag: '1698378560692',
messageType: 'message',
createdDateTime: '2023-10-27T03:49:20.692Z',
lastModifiedDateTime: '2023-10-27T03:49:20.692Z',
lastEditedDateTime: null,
deletedDateTime: null,
subject: null,
summary: null,
chatId: '19:ebed9ad42c904d6c83adf0db360053ec@thread.v2',
importance: 'normal',
locale: 'en-us',
webUrl: null,
channelIdentity: null,
policyViolation: null,
eventDetail: null,
from: {
application: null,
device: null,
user: {
'@odata.type': '#microsoft.graph.teamworkUserIdentity',
id: '11111-2222-3333',
displayName: 'Michael Kret',
userIdentityType: 'aadUser',
tenantId: '23786ca6-7ff2-4672-87d0-5c649ee0a337',
},
},
body: {
contentType: 'html',
content:
'Hello!<br>\n<br>\n<em> Powered by <a href="http://localhost:5678/workflow/i3NYGF0LXV4qDFV9?utm_source=n8n-internal&amp;utm_medium=powered_by&amp;utm_campaign=n8n-nodes-base.microsoftTeams_b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363">this n8n workflow</a> </em>',
},
attachments: [],
mentions: [],
reactions: [],
},
{
id: '1698129297101',
replyToId: null,
etag: '1698129297101',
messageType: 'message',
createdDateTime: '2023-10-24T06:34:57.101Z',
lastModifiedDateTime: '2023-10-24T06:34:57.101Z',
lastEditedDateTime: null,
deletedDateTime: null,
subject: null,
summary: null,
chatId: '19:ebed9ad42c904d6c83adf0db360053ec@thread.v2',
importance: 'normal',
locale: 'en-us',
webUrl: null,
channelIdentity: null,
policyViolation: null,
eventDetail: null,
from: {
application: null,
device: null,
user: {
'@odata.type': '#microsoft.graph.teamworkUserIdentity',
id: '11111-2222-3333',
displayName: 'Michael Kret',
userIdentityType: 'aadUser',
tenantId: '23786ca6-7ff2-4672-87d0-5c649ee0a337',
},
},
body: {
contentType: 'html',
content:
'tada<br>\n<br>\n<em> Powered by <a href="http://localhost:5678/workflow/5sTm8tp3j3niFewr?utm_source=n8n-internal&amp;utm_medium=powered_by&amp;utm_campaign=n8n-nodes-base.microsoftTeams_b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363">this n8n workflow</a> </em>',
},
attachments: [],
mentions: [],
reactions: [],
},
];
}
});
describe('Test MicrosoftTeamsV2, chatMessage => getAll', () => { describe('Test MicrosoftTeamsV2, chatMessage => getAll', () => {
const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.workflow.json']; nock('https://graph.microsoft.com')
const tests = workflowToTests(workflows); .get('/v1.0/chats/19:ebed9ad42c904d6c83adf0db360053ec@thread.v2/messages')
const nodeTypes = setup(tests); .reply(200, {
value: [
const testNode = async (testData: WorkflowTestData, types: INodeTypes) => { {
const { result } = await executeWorkflow(testData, types); id: '1698378560692',
replyToId: null,
const resultNodeData = getResultNodeData(result, testData); etag: '1698378560692',
messageType: 'message',
resultNodeData.forEach(({ nodeName, resultData }) => { createdDateTime: '2023-10-27T03:49:20.692Z',
return expect(resultData).toEqual(testData.output.nodeData[nodeName]); lastModifiedDateTime: '2023-10-27T03:49:20.692Z',
lastEditedDateTime: null,
deletedDateTime: null,
subject: null,
summary: null,
chatId: '19:ebed9ad42c904d6c83adf0db360053ec@thread.v2',
importance: 'normal',
locale: 'en-us',
webUrl: null,
channelIdentity: null,
policyViolation: null,
eventDetail: null,
from: {
application: null,
device: null,
user: {
'@odata.type': '#microsoft.graph.teamworkUserIdentity',
id: '11111-2222-3333',
displayName: 'Michael Kret',
userIdentityType: 'aadUser',
tenantId: '23786ca6-7ff2-4672-87d0-5c649ee0a337',
},
},
body: {
contentType: 'html',
content:
'Hello!<br>\n<br>\n<em> Powered by <a href="http://localhost:5678/workflow/i3NYGF0LXV4qDFV9?utm_source=n8n-internal&amp;utm_medium=powered_by&amp;utm_campaign=n8n-nodes-base.microsoftTeams_b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363">this n8n workflow</a> </em>',
},
attachments: [],
mentions: [],
reactions: [],
},
{
id: '1698129297101',
replyToId: null,
etag: '1698129297101',
messageType: 'message',
createdDateTime: '2023-10-24T06:34:57.101Z',
lastModifiedDateTime: '2023-10-24T06:34:57.101Z',
lastEditedDateTime: null,
deletedDateTime: null,
subject: null,
summary: null,
chatId: '19:ebed9ad42c904d6c83adf0db360053ec@thread.v2',
importance: 'normal',
locale: 'en-us',
webUrl: null,
channelIdentity: null,
policyViolation: null,
eventDetail: null,
from: {
application: null,
device: null,
user: {
'@odata.type': '#microsoft.graph.teamworkUserIdentity',
id: '11111-2222-3333',
displayName: 'Michael Kret',
userIdentityType: 'aadUser',
tenantId: '23786ca6-7ff2-4672-87d0-5c649ee0a337',
},
},
body: {
contentType: 'html',
content:
'tada<br>\n<br>\n<em> Powered by <a href="http://localhost:5678/workflow/5sTm8tp3j3niFewr?utm_source=n8n-internal&amp;utm_medium=powered_by&amp;utm_campaign=n8n-nodes-base.microsoftTeams_b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363">this n8n workflow</a> </em>',
},
attachments: [],
mentions: [],
reactions: [],
},
],
}); });
expect(microsoftApiRequestSpy).toHaveBeenCalledTimes(1); const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.workflow.json'];
expect(microsoftApiRequestSpy).toHaveBeenCalledWith( testWorkflows(workflows);
'value',
'GET',
'/v1.0/chats/19:ebed9ad42c904d6c83adf0db360053ec@thread.v2/messages',
{},
);
expect(result.finished).toEqual(true);
};
for (const testData of tests) {
test(testData.description, async () => await testNode(testData, nodeTypes));
}
}); });

Some files were not shown because too many files have changed in this diff Show More