From 979f9e6327c83f05f2603e49ca7bf9c54acc765f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 29 Apr 2025 17:42:21 +0200 Subject: [PATCH] refactor: Overhaul nodes-testing setup - Part 3 (no-changelog) (#14967) --- .../OpenAi/test/OpenAI.workflow.test.ts | 79 ++++ .../OpenAi/test/list-assistants.workflow.json | 43 +++ packages/@n8n/nodes-langchain/tsconfig.json | 5 +- packages/core/.eslintrc.js | 2 +- .../nodes-testing}/credential-types.ts | 0 .../nodes-testing}/credentials-helper.ts | 10 +- .../load-nodes-and-credentials.ts | 97 +++++ .../core/nodes-testing/node-test-harness.ts | 341 ++++++++++++++++++ .../nodes-testing}/node-types.ts | 0 .../nodes/Airtable/test/Airtable.node.test.ts | 52 ++- .../nodes/Airtable/test/workflow.json | 13 +- .../test/AwsComprehend.node.test.ts | 7 +- .../test/AwsRekognition.node.test.ts | 6 +- .../nodes/Aws/S3/test/V1/AwsS3.node.test.ts | 7 +- .../nodes/Aws/S3/test/V2/AwsS3.node.test.ts | 7 +- .../nodes/Aws/SES/test/AwsSes.node.test.ts | 19 +- .../__tests__/workflow/workflow.test.ts | 6 +- .../nodes/Code/test/Code.node.test.ts | 7 +- .../test/node/CompareDatasets.test.ts | 8 +- .../Compression/test/node/Compression.test.ts | 24 +- .../nodes/Crypto/test/Crypto.test.ts | 7 +- .../nodes/DateTime/test/node/DateTime.test.ts | 19 +- .../test/v2/node/channel/create.test.ts | 8 +- .../v2/node/channel/deleteChannel.test.ts | 8 +- .../Discord/test/v2/node/channel/get.test.ts | 8 +- .../test/v2/node/channel/getAll.test.ts | 8 +- .../test/v2/node/channel/update.test.ts | 8 +- .../test/v2/node/member/getAll.test.ts | 8 +- .../test/v2/node/member/roleAdd.test.ts | 8 +- .../test/v2/node/member/roleRemove.test.ts | 8 +- .../v2/node/message/deleteMessage.test.ts | 8 +- .../Discord/test/v2/node/message/get.test.ts | 8 +- .../test/v2/node/message/getAll.test.ts | 8 +- .../test/v2/node/message/react.test.ts | 8 +- .../Discord/test/v2/node/message/send.test.ts | 8 +- .../test/v2/node/webhook/sendLegacy.test.ts | 9 +- .../EvaluationMetrics.node.test.ts | 2 +- .../test/ExecuteCommand.node.test.ts | 7 +- .../test/ExecutionData.node.test.ts | 8 +- .../test/ConvertToFile.node.test.ts | 8 +- .../test/ExtractFromFile.node.test.ts | 5 +- .../ReadWriteFile/actions/read.operation.ts | 1 - .../ReadWriteFile/test/ReadWriteFile.test.ts | 35 +- .../nodes/Files/test/ConvertExtract.test.ts | 8 +- .../nodes/Filter/test/Filter.node.test.ts | 8 +- packages/nodes-base/nodes/Form/utils.ts | 2 +- .../node/Github.dispatchAndWait.node.test.ts | 13 +- .../Github/__tests__/node/Github.node.test.ts | 11 +- .../nodes/Gong/test/Gong.node.test.ts | 70 +--- .../test/v2/node/executeQuery.test.ts | 8 +- .../test/v2/node/insert.autoMapMode.test.ts | 8 +- .../test/v2/node/insert.manualMode.test.ts | 8 +- .../Google/Gmail/test/v1/GmailV1.node.test.ts | 19 +- .../Google/Gmail/test/v2/GmailV2.node.test.ts | 19 +- .../__test__/node/YouTube.node.test.ts | 28 +- .../nodes/GraphQL/test/GraphQL.node.test.ts | 6 +- .../nodes/Html/test/Html.node.test.ts | 8 +- .../HtmlExtract/test/HtmlExtract.node.test.ts | 8 +- .../test/binaryData/HttpRequest.test.ts | 6 +- .../test/binaryData/binaryData.test.json | 41 +-- .../test/encoding/HttpRequest.test.ts | 6 +- .../test/encodingQuoted/HttpRequest.test.ts | 6 +- .../HttpRequest/test/node/HttpRequest.test.ts | 6 +- .../Hubspot/__test__/Hubspot.node.test.ts | 15 +- .../ICalendar/test/node/ICalendar.test.ts | 46 +-- .../nodes/If/test/v1/If.node.test.ts | 8 +- .../nodes/If/test/v2/IfV2.node.test.ts | 7 +- .../ItemLists/test/node/ItemLists.test.ts | 8 +- .../GenericFunctions.test.ts | 0 .../{ => __test__}/JiraTrigger.node.test.ts | 2 +- .../{test => __test__}/node.methods.test.ts | 0 .../nodes/Jwt/test/Jwt.node.test.ts | 8 +- .../nodes/Kafka/{ => test}/Kafka.node.test.ts | 7 +- .../{ => test}/KafkaTrigger.node.test.ts | 2 +- .../tests/v1/MailerLite.v1.workflow.test.ts | 6 +- .../tests/v2/MailerLite.v2.workflow.test.ts | 6 +- .../nodes/Markdown/test/node/Markdown.test.ts | 8 +- .../nodes/Merge/test/node/Merge.test.ts | 8 +- .../test/container/create.test.ts | 12 +- .../test/container/delete.test.ts | 12 +- .../AzureCosmosDb/test/container/get.test.ts | 12 +- .../test/container/getAll.test.ts | 12 +- .../AzureCosmosDb/test/item/create.test.ts | 12 +- .../AzureCosmosDb/test/item/delete.test.ts | 12 +- .../AzureCosmosDb/test/item/get.test.ts | 12 +- .../AzureCosmosDb/test/item/getAll.test.ts | 12 +- .../AzureCosmosDb/test/item/query.test.ts | 12 +- .../AzureCosmosDb/test/item/update.test.ts | 12 +- .../Entra/test/GroupDescription.test.ts | 25 +- .../Entra/test/MicrosoftEntra.node.test.ts | 18 +- .../Entra/test/UserDescription.test.ts | 27 +- .../Excel/test/v2/node/table/addTable.test.ts | 9 +- .../Excel/test/v2/node/table/append.test.ts | 9 +- .../test/v2/node/table/convertToRange.test.ts | 9 +- .../test/v2/node/table/deleteTable.test.ts | 9 +- .../test/v2/node/table/getColumns.test.ts | 9 +- .../Excel/test/v2/node/table/getRows.test.ts | 9 +- .../Excel/test/v2/node/table/lookup.test.ts | 9 +- .../v2/node/workbook/addWorksheet.test.ts | 9 +- .../v2/node/workbook/deleteWorkbook.test.ts | 9 +- .../test/v2/node/workbook/getAll.test.ts | 9 +- .../test/v2/node/worksheet/append.test.ts | 9 +- .../test/v2/node/worksheet/clear.test.ts | 9 +- .../v2/node/worksheet/deleteWorksheet.test.ts | 9 +- .../test/v2/node/worksheet/getAll.test.ts | 9 +- .../test/v2/node/worksheet/readRows.test.ts | 9 +- .../test/v2/node/worksheet/update.test.ts | 9 +- .../test/v2/node/worksheet/upsert.test.ts | 9 +- .../test/v2/node/calendar/create.test.ts | 8 +- .../test/v2/node/calendar/delete.test.ts | 8 +- .../Outlook/test/v2/node/calendar/get.test.ts | 8 +- .../test/v2/node/calendar/getAll.test.ts | 8 +- .../test/v2/node/calendar/update.test.ts | 8 +- .../test/v2/node/contact/create.test.ts | 8 +- .../test/v2/node/contact/update.test.ts | 8 +- .../Outlook/test/v2/node/draft/create.test.ts | 8 +- .../Outlook/test/v2/node/draft/send.test.ts | 8 +- .../Outlook/test/v2/node/event/create.test.ts | 8 +- .../test/v2/node/folder/create.test.ts | 8 +- .../test/v2/node/folderMessage/getAll.test.ts | 8 +- .../Outlook/test/v2/node/message/move.test.ts | 8 +- .../test/v2/node/message/reply.test.ts | 8 +- .../Outlook/test/v2/node/message/send.test.ts | 8 +- .../blob_create.workflow.json | 0 .../blob_delete.workflow.json | 0 .../blob_get.workflow.json | 1 + .../blob_getAll.workflow.json | 0 .../blob_getAllLimitOptions.workflow.json | 0 .../Storage/test/blob/create.test.ts | 109 +++--- .../Storage/test/blob/delete.test.ts | 47 ++- .../Microsoft/Storage/test/blob/get.test.ts | 153 ++++---- .../Storage/test/blob/getAll.test.ts | 50 ++- .../test/blob/getAllLimitOptions.test.ts | 39 +- .../container_create.workflow.json | 0 .../container_delete.workflow.json | 0 .../container_get.workflow.json | 0 .../container_getAll.workflow.json | 0 ...container_getAllLimitOptions.workflow.json | 0 .../Storage/test/container/create.test.ts | 54 ++- .../Storage/test/container/delete.test.ts | 48 ++- .../Storage/test/container/get.test.ts | 66 ++-- .../Storage/test/container/getAll.test.ts | 50 ++- .../test/container/getAllLimitOptions.test.ts | 39 +- .../credentials_oauth2.workflow.json | 0 .../credentials_sharedKey.workflow.json | 0 .../Storage/test/credentials/oauth2.test.ts | 68 ++-- .../test/credentials/sharedKey.test.ts | 67 ++-- .../test/listSearch/listSearch.test.ts | 12 +- .../Teams/test/v2/node/channel/create.test.ts | 9 +- .../v2/node/channel/deleteChannel.test.ts | 9 +- .../Teams/test/v2/node/channel/get.test.ts | 9 +- .../Teams/test/v2/node/channel/getAll.test.ts | 9 +- .../Teams/test/v2/node/channel/update.test.ts | 9 +- .../v2/node/channelMessage/create.test.ts | 9 +- .../v2/node/channelMessage/getAll.test.ts | 9 +- .../test/v2/node/chatMessage/create.test.ts | 9 +- .../test/v2/node/chatMessage/get.test.ts | 9 +- .../test/v2/node/chatMessage/getAll.test.ts | 9 +- .../Teams/test/v2/node/task/create.test.ts | 9 +- .../test/v2/node/task/deleteTask.test.ts | 9 +- .../Teams/test/v2/node/task/get.test.ts | 9 +- .../Teams/test/v2/node/task/getAll.test.ts | 9 +- .../Teams/test/v2/node/task/update.test.ts | 9 +- .../test/MoveBinaryData.test.ts | 26 +- .../nodes/MySql/test/v1/executeQuery.test.ts | 37 +- .../nodes/N8n/test/node/N8n.test.ts | 31 +- .../Notion/test/node/v2/block/append.test.ts | 8 +- .../Notion/test/node/v2/block/getAll.test.ts | 8 +- .../Notion/test/node/v2/database/get.test.ts | 8 +- .../test/node/v2/database/getAll.test.ts | 8 +- .../test/node/v2/database/search.test.ts | 8 +- .../test/node/v2/databasePage/create.test.ts | 8 +- .../test/node/v2/databasePage/get.test.ts | 8 +- .../test/node/v2/databasePage/getAll.test.ts | 8 +- .../test/node/v2/databasePage/update.test.ts | 8 +- .../Notion/test/node/v2/page/archive.test.ts | 8 +- .../Notion/test/node/v2/page/create.test.ts | 8 +- .../Notion/test/node/v2/page/search.test.ts | 8 +- .../Notion/test/node/v2/user/get.test.ts | 8 +- .../Notion/test/node/v2/user/getAll.test.ts | 8 +- .../nodes/Npm/test/Npm.node.test.ts | 6 +- .../test/OpenWeatherMap.test.ts | 6 +- .../nodes/Oura/test/oura.node.test.ts | 7 +- .../Peekalink/test/Peekalink.node.test.ts | 18 +- .../nodes/PhilipsHue/test/workflow.test.ts | 6 +- .../QuickChart/test/QuickChart.node.test.ts | 21 +- .../test/ReadBinaryFile.test.ts | 27 +- .../test/ReadBinaryFiles.test.ts | 28 +- .../test/ReadPDF-encrypted.workflow.json | 1 + .../nodes/ReadPdf/test/ReadPDF.test.ts | 6 +- .../nodes/ReadPdf/test/ReadPDF.workflow.json | 1 + .../nodes/RenameKeys/test/RenameKeys.test.ts | 8 +- .../RssFeedRead/test/node/RssFeedRead.test.ts | 6 +- .../__test__/node/Salesforce.node.test.ts | 28 +- .../v2/actions/asset/upload.operation.ts | 2 +- .../SeaTable/v2/actions/row/get.operation.ts | 2 +- .../SeaTable/v2/actions/row/list.operation.ts | 2 +- .../v2/actions/row/search.operation.ts | 2 +- .../nodes/SendGrid/test/SendGrid.node.test.ts | 7 +- .../nodes/Set/test/Set.node.test.ts | 7 +- .../test/v2/node/channel/archive.test.ts | 8 +- .../Slack/test/v2/node/channel/create.test.ts | 8 +- .../Slack/test/v2/node/channel/get.test.ts | 8 +- .../Slack/test/v2/node/channel/getAll.test.ts | 8 +- .../test/v2/node/channel/history.test.ts | 8 +- .../Slack/test/v2/node/file/upload.test.ts | 8 +- .../Slack/test/v2/node/message/delete.test.ts | 8 +- .../test/v2/node/message/getPermalink.test.ts | 8 +- .../Slack/test/v2/node/message/post.test.ts | 8 +- .../Slack/test/v2/node/message/search.test.ts | 8 +- .../Slack/test/v2/node/message/update.test.ts | 8 +- .../test/v2/node/user/updateProfile.test.ts | 8 +- .../test/SplitInBatches.node.test.ts | 7 +- .../__tests__/workflow/workflow.test.ts | 6 +- .../test/SpreadsheetFile.test.ts | 32 +- .../nodes/Start/__tests__/StartNode.test.ts | 18 +- .../test/node/StopAndError.test.ts | 42 +-- .../nodes/Switch/V1/test/switch.node.test.ts | 7 +- .../nodes/Switch/V2/test/switch.node.test.ts | 7 +- .../nodes/Switch/V3/test/switch.node.test.ts | 7 +- .../Telegram/tests/Workflow/workflow.test.ts | 6 +- .../nodes/Totp/test/Totp.node.test.ts | 24 +- .../Aggregate/test/Aggregate.test.ts | 8 +- .../nodes/Transform/Limit/test/Limit.test.ts | 8 +- .../test/RemoveDuplicates.test.ts | 11 +- .../nodes/Transform/Sort/test/Sort.test.ts | 8 +- .../Transform/SplitOut/test/SplitOut.test.ts | 8 +- .../Summarize/test/Summarize.test.ts | 8 +- .../nodes/Twitter/test/Twitter.test.ts | 6 +- .../nodes/Wait/test/Wait.node.test.ts | 7 +- .../nodes/Webhook/test/Webhook.test.ts | 7 +- .../__tests__/workflow/page/page.test.ts | 7 +- .../__tests__/workflow/post/post.test.ts | 7 +- .../__tests__/workflow/user/user.test.ts | 7 +- .../test/WriteBinaryFile.test.ts | 32 +- .../nodes/Xml/test/node/Xml.test.ts | 8 +- .../nodes-base/test/nodes/ExecuteWorkflow.ts | 102 ------ packages/nodes-base/test/nodes/Helpers.ts | 185 +--------- .../test/nodes/load-nodes-and-credentials.ts | 48 --- packages/nodes-base/tsconfig.json | 3 +- packages/workflow/src/Interfaces.ts | 3 + 241 files changed, 1868 insertions(+), 2013 deletions(-) create mode 100644 packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/OpenAI.workflow.test.ts create mode 100644 packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/list-assistants.workflow.json rename packages/{nodes-base/test/nodes => core/nodes-testing}/credential-types.ts (100%) rename packages/{nodes-base/test/nodes => core/nodes-testing}/credentials-helper.ts (88%) create mode 100644 packages/core/nodes-testing/load-nodes-and-credentials.ts create mode 100644 packages/core/nodes-testing/node-test-harness.ts rename packages/{nodes-base/test/nodes => core/nodes-testing}/node-types.ts (100%) rename packages/nodes-base/nodes/EvaluationMetrics/{ => __tests__}/EvaluationMetrics.node.test.ts (97%) rename packages/nodes-base/nodes/Jira/{test => __test__}/GenericFunctions.test.ts (100%) rename packages/nodes-base/nodes/Jira/{ => __test__}/JiraTrigger.node.test.ts (99%) rename packages/nodes-base/nodes/Jira/{test => __test__}/node.methods.test.ts (100%) rename packages/nodes-base/nodes/Kafka/{ => test}/Kafka.node.test.ts (92%) rename packages/nodes-base/nodes/Kafka/{ => test}/KafkaTrigger.node.test.ts (99%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => blob}/blob_create.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => blob}/blob_delete.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => blob}/blob_get.workflow.json (97%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => blob}/blob_getAll.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => blob}/blob_getAllLimitOptions.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => container}/container_create.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => container}/container_delete.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => container}/container_get.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => container}/container_getAll.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => container}/container_getAllLimitOptions.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => credentials}/credentials_oauth2.workflow.json (100%) rename packages/nodes-base/nodes/Microsoft/Storage/test/{workflows => credentials}/credentials_sharedKey.workflow.json (100%) delete mode 100644 packages/nodes-base/test/nodes/ExecuteWorkflow.ts delete mode 100644 packages/nodes-base/test/nodes/load-nodes-and-credentials.ts diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/OpenAI.workflow.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/OpenAI.workflow.test.ts new file mode 100644 index 0000000000..543e9db37e --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/OpenAI.workflow.test.ts @@ -0,0 +1,79 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; +import { pick } from 'lodash'; +import type { WorkflowTestData } from 'n8n-workflow'; +import path from 'node:path'; + +describe('OpenAI Workflow', () => { + const baseUrl = 'https://api.openai.com/v1'; + const credentials = { + openAiApi: { url: baseUrl }, + }; + + const testHarness = new NodeTestHarness({ + additionalPackagePaths: [path.dirname(require.resolve('n8n-nodes-base'))], + }); + + const assistants = [ + { + id: 'asst_abc123', + object: 'assistant', + created_at: 1698982736, + name: 'Coding Tutor', + description: null, + model: 'gpt-4o', + tools: [], + tool_resources: {}, + metadata: {}, + top_p: 1.0, + temperature: 1.0, + response_format: 'auto', + }, + { + id: 'asst_abc456', + object: 'assistant', + created_at: 1698982718, + name: 'My Assistant', + description: null, + model: 'gpt-4o', + tools: [], + tool_resources: {}, + metadata: {}, + top_p: 1.0, + temperature: 1.0, + response_format: 'auto', + }, + ]; + + const testData: WorkflowTestData = { + description: 'List Assistants', + input: { + workflowData: testHarness.readWorkflowJSON('list-assistants.workflow.json'), + }, + output: { + nodeExecutionOrder: ['When clicking ‘Test workflow’', 'OpenAI'], + nodeData: { + OpenAI: [ + assistants.map((assistant) => ({ + json: pick(assistant, ['id', 'model', 'name']), + })), + ], + }, + }, + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/assistants?limit=100', + statusCode: 200, + responseBody: { + object: 'list', + data: assistants, + }, + }, + ], + }, + }; + + testHarness.setupTest(testData, { credentials }); +}); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/list-assistants.workflow.json b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/list-assistants.workflow.json new file mode 100644 index 0000000000..5ee85a1a98 --- /dev/null +++ b/packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/test/list-assistants.workflow.json @@ -0,0 +1,43 @@ +{ + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [0, 0], + "id": "ce6133c3-2eb6-4262-8e0c-54015ed0f795", + "name": "When clicking ‘Test workflow’" + }, + { + "parameters": { + "resource": "assistant", + "operation": "list" + }, + "type": "@n8n/n8n-nodes-langchain.openAi", + "typeVersion": 1.8, + "position": [220, 0], + "id": "070d2fcc-032c-4c3f-ae33-80a5352785f8", + "name": "OpenAI", + "credentials": { + "openAiApi": { + "id": "123", + "name": "OpenAi account" + } + } + } + ], + "connections": { + "When clicking ‘Test workflow’": { + "main": [ + [ + { + "node": "OpenAI", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "pinData": {} +} diff --git a/packages/@n8n/nodes-langchain/tsconfig.json b/packages/@n8n/nodes-langchain/tsconfig.json index 2ea84de001..5769fd8071 100644 --- a/packages/@n8n/nodes-langchain/tsconfig.json +++ b/packages/@n8n/nodes-langchain/tsconfig.json @@ -6,9 +6,12 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@utils/*": ["./utils/*"] + "@utils/*": ["./utils/*"], + "@nodes-testing/*": ["../../core/nodes-testing/*"] }, "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, // TODO: remove all options below this line "useUnknownInCatchVariables": false }, diff --git a/packages/core/.eslintrc.js b/packages/core/.eslintrc.js index a69b1abddb..849d69fe55 100644 --- a/packages/core/.eslintrc.js +++ b/packages/core/.eslintrc.js @@ -12,7 +12,7 @@ module.exports = { project: './tsconfig.json', }, - ignorePatterns: ['bin/*.js'], + ignorePatterns: ['bin/*.js', 'nodes-testing/*.ts'], rules: { complexity: 'error', diff --git a/packages/nodes-base/test/nodes/credential-types.ts b/packages/core/nodes-testing/credential-types.ts similarity index 100% rename from packages/nodes-base/test/nodes/credential-types.ts rename to packages/core/nodes-testing/credential-types.ts diff --git a/packages/nodes-base/test/nodes/credentials-helper.ts b/packages/core/nodes-testing/credentials-helper.ts similarity index 88% rename from packages/nodes-base/test/nodes/credentials-helper.ts rename to packages/core/nodes-testing/credentials-helper.ts index 549c19635b..6aa096ecb6 100644 --- a/packages/nodes-base/test/nodes/credentials-helper.ts +++ b/packages/core/nodes-testing/credentials-helper.ts @@ -1,5 +1,4 @@ -import { Container, Service } from '@n8n/di'; -import { Credentials } from 'n8n-core'; +import { Service } from '@n8n/di'; import { ICredentialsHelper } from 'n8n-workflow'; import type { ICredentialDataDecryptedObject, @@ -10,12 +9,17 @@ import type { IWorkflowExecuteAdditionalData, } from 'n8n-workflow'; +import { Credentials } from '../dist/credentials'; import { CredentialTypes } from './credential-types'; @Service() export class CredentialsHelper extends ICredentialsHelper { private credentialsMap: Record = {}; + constructor(private readonly credentialTypes: CredentialTypes) { + super(); + } + setCredentials(credentialsMap: Record) { this.credentialsMap = credentialsMap; } @@ -29,7 +33,7 @@ export class CredentialsHelper extends ICredentialsHelper { typeName: string, requestParams: IHttpRequestOptions, ): Promise { - const credentialType = Container.get(CredentialTypes).getByName(typeName); + const credentialType = this.credentialTypes.getByName(typeName); if (typeof credentialType.authenticate === 'function') { return await credentialType.authenticate(credentials, requestParams); } diff --git a/packages/core/nodes-testing/load-nodes-and-credentials.ts b/packages/core/nodes-testing/load-nodes-and-credentials.ts new file mode 100644 index 0000000000..924e6653b3 --- /dev/null +++ b/packages/core/nodes-testing/load-nodes-and-credentials.ts @@ -0,0 +1,97 @@ +import { Service } from '@n8n/di'; +import type { + ICredentialType, + INodeType, + IVersionedNodeType, + KnownNodesAndCredentials, + LoadedClass, + LoadedNodesAndCredentials, + LoadingDetails, +} from 'n8n-workflow'; +import path from 'node:path'; + +import { UnrecognizedCredentialTypeError, UnrecognizedNodeTypeError } from '../dist/errors'; +import { LazyPackageDirectoryLoader } from '../dist/nodes-loader/lazy-package-directory-loader'; + +/** This rewrites the nodes/credentials source path to load the typescript code instead of the compiled javascript code */ +const fixSourcePath = (loadInfo: LoadingDetails) => { + if (!loadInfo) return; + loadInfo.sourcePath = loadInfo.sourcePath.replace(/^dist\//, './').replace(/\.js$/, '.ts'); +}; + +@Service() +export class LoadNodesAndCredentials { + private loaders: Record = {}; + + readonly known: KnownNodesAndCredentials = { nodes: {}, credentials: {} }; + + readonly loaded: LoadedNodesAndCredentials = { nodes: {}, credentials: {} }; + + constructor(packagePaths: string[]) { + for (const packagePath of packagePaths) { + const loader = new LazyPackageDirectoryLoader(packagePath); + this.loaders[loader.packageName] = loader; + } + } + + async init() { + for (const [packageName, loader] of Object.entries(this.loaders)) { + await loader.loadAll(); + const { known, directory } = loader; + + for (const type in known.nodes) { + const { className, sourcePath } = known.nodes[type]; + this.known.nodes[`${packageName}.${type}`] = { + className, + sourcePath: path.join(directory, sourcePath), + }; + } + + for (const type in known.credentials) { + const { + className, + sourcePath, + supportedNodes, + extends: extendsArr, + } = known.credentials[type]; + this.known.credentials[type] = { + className, + sourcePath: path.join(directory, sourcePath), + supportedNodes: supportedNodes?.map((nodeName) => `${loader.packageName}.${nodeName}`), + extends: extendsArr, + }; + } + } + } + + recognizesCredential(credentialType: string): boolean { + return credentialType in this.known.credentials; + } + + getCredential(credentialType: string): LoadedClass { + for (const loader of Object.values(this.loaders)) { + if (credentialType in loader.known.credentials) { + const loaded = loader.getCredential(credentialType); + this.loaded.credentials[credentialType] = loaded; + fixSourcePath(loader.known.credentials[credentialType]); + } + } + + if (credentialType in this.loaded.credentials) { + return this.loaded.credentials[credentialType]; + } + + throw new UnrecognizedCredentialTypeError(credentialType); + } + + getNode(fullNodeType: string): LoadedClass { + const [packageName, nodeType] = fullNodeType.split('.'); + const { loaders } = this; + const loader = loaders[packageName]; + if (!loader) { + throw new UnrecognizedNodeTypeError(packageName, nodeType); + } + fixSourcePath(loader.known.nodes[nodeType]); + return loader.getNode(nodeType); + } +} diff --git a/packages/core/nodes-testing/node-test-harness.ts b/packages/core/nodes-testing/node-test-harness.ts new file mode 100644 index 0000000000..43100c2e7c --- /dev/null +++ b/packages/core/nodes-testing/node-test-harness.ts @@ -0,0 +1,341 @@ +import { Memoized } from '@n8n/decorators'; +import { Container } from '@n8n/di'; +import callsites from 'callsites'; +import glob from 'fast-glob'; +import { mock } from 'jest-mock-extended'; +import { isEmpty } from 'lodash'; +import type { + ICredentialDataDecryptedObject, + IRun, + IRunExecutionData, + IWorkflowBase, + IWorkflowExecuteAdditionalData, + WorkflowTestData, +} from 'n8n-workflow'; +import { createDeferredPromise, UnexpectedError, Workflow } from 'n8n-workflow'; +import nock from 'nock'; +import { readFileSync, mkdtempSync, existsSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; + +import { ExecutionLifecycleHooks } from '../dist/execution-engine/execution-lifecycle-hooks'; +import { WorkflowExecute } from '../dist/execution-engine/workflow-execute'; +import { CredentialsHelper } from './credentials-helper'; +import { LoadNodesAndCredentials } from './load-nodes-and-credentials'; +import { NodeTypes } from './node-types'; + +type NodeOutputs = WorkflowTestData['output']['nodeData']; + +type TestHarnessOptions = { + additionalPackagePaths?: string[]; +}; + +type TestOptions = { + credentials?: Record; + assertBinaryData?: boolean; + workflowFiles?: string[]; + nock?: WorkflowTestData['nock']; + customAssertions?: () => void; +}; + +export class NodeTestHarness { + private readonly testDir: string; + + private readonly packagePaths: string[]; + + constructor({ additionalPackagePaths }: TestHarnessOptions = {}) { + this.testDir = path.dirname(callsites()[1].getFileName()!); + this.packagePaths = additionalPackagePaths ?? []; + this.packagePaths.unshift(this.packageDir); + + beforeEach(() => nock.disableNetConnect()); + } + + readWorkflowJSON(filePath: string) { + if (!filePath.startsWith(this.relativePath)) { + filePath = path.join(this.testDir, filePath); + } + return JSON.parse(readFileSync(filePath, 'utf-8')) as IWorkflowBase & + Pick; + } + + setupTests(options: TestOptions = {}) { + const workflowFilenames = + options.workflowFiles?.map((fileName) => path.join(this.relativePath, fileName)) ?? + this.workflowFilenames; + + const tests = this.workflowToTests(workflowFilenames, options); + for (const testData of tests) { + this.setupTest(testData, options); + } + } + + setupTest(testData: WorkflowTestData, options: TestOptions = {}) { + if (options.assertBinaryData) testData.output.assertBinaryData = true; + if (options.credentials) testData.credentials = options.credentials; + if (options.nock) testData.nock = options.nock; + + test(testData.description, async () => { + if (testData.nock) this.setupNetworkMocks(testData.nock); + const { result, nodeExecutionOrder } = await this.executeWorkflow(testData); + this.assertOutput(testData, result, nodeExecutionOrder); + + if (options.customAssertions) options.customAssertions(); + }); + } + + @Memoized + get temporaryDir() { + const dir = mkdtempSync(path.join(tmpdir(), 'n8n-')); + afterAll(() => rmSync(dir, { recursive: true })); + return dir; + } + + private workflowToTests(workflowFiles: string[], options: TestOptions = {}) { + const testCases: WorkflowTestData[] = []; + for (const filePath of workflowFiles) { + const description = filePath.replace('.json', ''); + const workflowData = this.readWorkflowJSON(filePath); + workflowData.nodes.forEach((node) => { + if (node.parameters) { + node.parameters = JSON.parse( + JSON.stringify(node.parameters).replace(/"C:\\\\Test\\\\(.*)"/, `"${this.testDir}/$1"`), + ); + } + }); + + const { pinData } = workflowData; + if (pinData === undefined) { + throw new UnexpectedError('Workflow data does not contain pinData'); + } + const nodeData = Object.keys(pinData).reduce((acc, key) => { + const items = pinData[key]; + acc[key] = [items]; + return acc; + }, {} as NodeOutputs); + delete workflowData.pinData; + + const { trigger } = workflowData; + delete workflowData.trigger; + + testCases.push({ + description, + input: { workflowData }, + output: { nodeData }, + trigger, + credentials: options.credentials, + }); + } + return testCases; + } + + @Memoized + private get packageDir() { + let packageDir = this.testDir; + while (packageDir !== '/') { + if (existsSync(path.join(packageDir, 'package.json'))) break; + packageDir = path.dirname(packageDir); + } + if (packageDir === '/') { + throw new UnexpectedError('Invalid package'); + } + return packageDir; + } + + @Memoized + private get relativePath() { + return path.relative(this.packageDir, this.testDir); + } + + @Memoized + private get workflowFilenames() { + return glob.sync(`${this.relativePath}/**/*.json`, { cwd: this.packageDir }); + } + + private setupNetworkMocks({ baseUrl, mocks }: NonNullable) { + const agent = nock(baseUrl); + mocks.forEach( + ({ + method, + path, + statusCode, + requestBody, + requestHeaders, + responseBody, + responseHeaders, + }) => { + let mock = agent[method](path, requestBody); + + // nock interceptor reqheaders option is ignored, so we chain matchHeader() + // agent[method](path, requestBody, { reqheaders: requestHeaders }).reply(statusCode, responseBody, responseHeaders) + // https://github.com/nock/nock/issues/2545 + if (requestHeaders && Object.keys(requestHeaders).length > 0) { + Object.entries(requestHeaders).forEach(([key, value]) => { + mock = mock.matchHeader(key, value); + }); + } + + mock.reply(statusCode, responseBody, responseHeaders); + }, + ); + } + + private async executeWorkflow(testData: WorkflowTestData) { + const loadNodesAndCredentials = new LoadNodesAndCredentials(this.packagePaths); + Container.set(LoadNodesAndCredentials, loadNodesAndCredentials); + await loadNodesAndCredentials.init(); + const nodeTypes = Container.get(NodeTypes); + const credentialsHelper = Container.get(CredentialsHelper); + credentialsHelper.setCredentials(testData.credentials ?? {}); + + const executionMode = testData.trigger?.mode ?? 'manual'; + const { connections, nodes, settings } = testData.input.workflowData; + const workflowInstance = new Workflow({ + id: 'test', + nodes, + connections, + nodeTypes, + settings, + active: false, + }); + + const hooks = new ExecutionLifecycleHooks('trigger', '1', mock()); + + const nodeExecutionOrder: string[] = []; + hooks.addHandler('nodeExecuteAfter', (nodeName) => { + nodeExecutionOrder.push(nodeName); + }); + + const waitPromise = createDeferredPromise(); + hooks.addHandler('workflowExecuteAfter', (fullRunData) => waitPromise.resolve(fullRunData)); + + const additionalData = mock({ + hooks, + // Get from node.parameters + currentNodeParameters: undefined, + }); + additionalData.credentialsHelper = credentialsHelper; + + let executionData: IRun; + const runExecutionData: IRunExecutionData = { + resultData: { + runData: {}, + }, + executionData: { + metadata: {}, + contextData: {}, + waitingExecution: {}, + waitingExecutionSource: null, + nodeExecutionStack: [ + { + node: workflowInstance.getStartNode()!, + data: { + main: [[testData.trigger?.input ?? { json: {} }]], + }, + source: null, + }, + ], + }, + }; + + const workflowExecute = new WorkflowExecute(additionalData, executionMode, runExecutionData); + executionData = await workflowExecute.processRunExecutionData(workflowInstance); + + const result = await waitPromise.promise; + return { executionData, result, nodeExecutionOrder }; + } + + private getResultNodeData(result: IRun, testData: WorkflowTestData) { + const { runData } = result.data.resultData; + return Object.keys(testData.output.nodeData).map((nodeName) => { + if (runData[nodeName] === undefined) { + // log errors from other nodes + Object.keys(runData).forEach((key) => { + const error = runData[key][0]?.error; + if (error) { + console.log(`Node ${key}\n`, error); + } + }); + + throw new UnexpectedError(`Data for node "${nodeName}" is missing!`); + } + const resultData = runData[nodeName].map((nodeData) => { + if (nodeData.data === undefined) { + return null; + } + // TODO: iterate all runIndexes + return nodeData.data.main[0]!.map((entry) => { + if (entry.binary && isEmpty(entry.binary)) delete entry.binary; + delete entry.pairedItem; + return entry; + }); + }); + return { + nodeName, + resultData, + }; + }); + } + + private assertOutput(testData: WorkflowTestData, result: IRun, nodeExecutionOrder: string[]) { + const { output } = testData; + + // Check if the nodes did executed in the correct order (if the test defines this) + if (output.nodeExecutionOrder?.length) { + expect(nodeExecutionOrder).toEqual(output.nodeExecutionOrder); + } + + const { + finished, + status, + data: { executionData, resultData }, + } = result; + if (output.nodeExecutionStack) { + expect(executionData?.nodeExecutionStack).toEqual(output.nodeExecutionStack); + } + + if (output.error) { + const { error } = resultData; + const errorMessage = (error?.cause ? error.cause : error)?.message; + expect(errorMessage).toBeDefined(); + expect(output.error).toBe(errorMessage); + expect(finished).toBeUndefined(); + return; + } + + // check if result node data matches expected test data + const resultNodeData = this.getResultNodeData(result, testData); + resultNodeData.forEach(({ nodeName, resultData }) => { + resultData.forEach((items) => { + items?.forEach((item) => { + const { binary, json } = item; + if (binary) { + if (!output.assertBinaryData) { + delete item.binary; + } else { + for (const key in binary) { + delete binary[key].directory; + } + } + } + + // Convert errors to JSON so tests can compare + if (json?.error instanceof Error) { + json.error = JSON.parse( + JSON.stringify(json.error, ['message', 'name', 'description', 'context']), + ); + } + }); + }); + + const msg = `Equality failed for "${testData.description}" at node "${nodeName}"`; + expect(resultData, msg).toEqual(output.nodeData[nodeName]); + }); + + if (finished) { + expect(status).toEqual('success'); + } else { + expect(status).toEqual('waiting'); + } + } +} diff --git a/packages/nodes-base/test/nodes/node-types.ts b/packages/core/nodes-testing/node-types.ts similarity index 100% rename from packages/nodes-base/test/nodes/node-types.ts rename to packages/core/nodes-testing/node-types.ts diff --git a/packages/nodes-base/nodes/Airtable/test/Airtable.node.test.ts b/packages/nodes-base/nodes/Airtable/test/Airtable.node.test.ts index 9037e09af5..f965bf6be7 100644 --- a/packages/nodes-base/nodes/Airtable/test/Airtable.node.test.ts +++ b/packages/nodes-base/nodes/Airtable/test/Airtable.node.test.ts @@ -1,44 +1,34 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import nock from 'nock'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - -const records = [ - { - id: 'rec2BWBoyS5QsS7pT', - createdTime: '2022-08-25T08:22:34.000Z', - fields: { - name: 'Tim', - email: 'tim@email.com', - }, - }, -]; +const record = { + id: 'rec2BWBoyS5QsS7pT', + name: 'Tim', + email: 'tim@email.com', + createdTime: '2022-08-25T08:22:34.000Z', +}; describe('Execute Airtable Node', () => { + const testHarness = new NodeTestHarness(); + beforeEach(() => { nock('https://api.airtable.com/v0') - .get('/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh?pageSize=100') - .reply(200, { records }); + .get('/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh/rec2BWBoyS5QsS7pT') + .reply(200, record); }); - const tests: WorkflowTestData[] = [ - { - description: 'List Airtable Records', - input: { - workflowData: Helpers.readJsonFileSync('nodes/Airtable/test/workflow.json'), - }, - output: { - nodeData: { - Airtable: [[...records.map((r) => ({ json: r }))]], - }, + const testData: WorkflowTestData = { + description: 'List Airtable Records', + input: { + workflowData: testHarness.readWorkflowJSON('workflow.json'), + }, + output: { + nodeData: { + Airtable: [[{ json: record }]], }, }, - ]; + }; - for (const testData of tests) { - test(testData.description, async () => { - await executeWorkflow(testData); - }); - } + testHarness.setupTest(testData, { credentials: { airtableTokenApi: {} } }); }); diff --git a/packages/nodes-base/nodes/Airtable/test/workflow.json b/packages/nodes-base/nodes/Airtable/test/workflow.json index b171c33df0..024d26fe3a 100644 --- a/packages/nodes-base/nodes/Airtable/test/workflow.json +++ b/packages/nodes-base/nodes/Airtable/test/workflow.json @@ -13,16 +13,19 @@ }, { "parameters": { - "operation": "list", + "base": "appIaXXdDqS5ORr4V", + "resource": "record", + "operation": "get", + "id": "rec2BWBoyS5QsS7pT", "application": { "__rl": true, - "value": "https://airtable.com/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh/viwInsMdsxffad0aU", + "value": "https://airtable.com/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh/rec2BWBoyS5QsS7pT", "mode": "url", "__regex": "https://airtable.com/([a-zA-Z0-9]{2,})" }, "table": { "__rl": true, - "value": "https://airtable.com/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh/viwInsMdsxffad0aU", + "value": "https://airtable.com/appIaXXdDqS5ORr4V/tbljyBEdYzCPF0NDh/rec2BWBoyS5QsS7pT", "mode": "url", "__regex": "https://airtable.com/[a-zA-Z0-9]{2,}/([a-zA-Z0-9]{2,})" }, @@ -31,10 +34,10 @@ "id": "5654d3b3-fe83-4988-889b-94f107d41807", "name": "Airtable", "type": "n8n-nodes-base.airtable", - "typeVersion": 1, + "typeVersion": 2, "position": [1020, 380], "credentials": { - "airtableApi": { + "airtableTokenApi": { "id": "20", "name": "Airtable account" } diff --git a/packages/nodes-base/nodes/Aws/Comprehend/test/AwsComprehend.node.test.ts b/packages/nodes-base/nodes/Aws/Comprehend/test/AwsComprehend.node.test.ts index e13bd8233f..374377f673 100644 --- a/packages/nodes-base/nodes/Aws/Comprehend/test/AwsComprehend.node.test.ts +++ b/packages/nodes-base/nodes/Aws/Comprehend/test/AwsComprehend.node.test.ts @@ -1,11 +1,8 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../__tests__/credentials'; -const workflows = getWorkflowFilenames(__dirname); - describe('Test AWS Comprehend Node', () => { describe('Detect Language', () => { let mock: nock.Scope; @@ -35,6 +32,6 @@ describe('Test AWS Comprehend Node', () => { mock.post('/').reply(200, response); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/Aws/Rekognition/test/AwsRekognition.node.test.ts b/packages/nodes-base/nodes/Aws/Rekognition/test/AwsRekognition.node.test.ts index 9d3d57411b..1ebd8e790e 100644 --- a/packages/nodes-base/nodes/Aws/Rekognition/test/AwsRekognition.node.test.ts +++ b/packages/nodes-base/nodes/Aws/Rekognition/test/AwsRekognition.node.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../__tests__/credentials'; const responseLabels = [ @@ -288,7 +287,6 @@ const responseLabels = [ describe('Test AWS Rekogntion Node', () => { describe('Image Labels Recognition', () => { - const workflows = getWorkflowFilenames(__dirname); const baseUrl = 'https://rekognition.eu-central-1.amazonaws.com'; let mock: nock.Scope; @@ -300,6 +298,6 @@ describe('Test AWS Rekogntion Node', () => { mock.post('/').reply(200, responseLabels); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/Aws/S3/test/V1/AwsS3.node.test.ts b/packages/nodes-base/nodes/Aws/S3/test/V1/AwsS3.node.test.ts index ffa3c2840d..e3360c7ee5 100644 --- a/packages/nodes-base/nodes/Aws/S3/test/V1/AwsS3.node.test.ts +++ b/packages/nodes-base/nodes/Aws/S3/test/V1/AwsS3.node.test.ts @@ -1,11 +1,8 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../__tests__/credentials'; -const workflows = getWorkflowFilenames(__dirname); - describe('Test S3 V1 Node', () => { describe('File Upload', () => { let mock: nock.Scope; @@ -39,6 +36,6 @@ describe('Test S3 V1 Node', () => { .reply(200, { success: true }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/Aws/S3/test/V2/AwsS3.node.test.ts b/packages/nodes-base/nodes/Aws/S3/test/V2/AwsS3.node.test.ts index cea98a1f0e..973d1d594d 100644 --- a/packages/nodes-base/nodes/Aws/S3/test/V2/AwsS3.node.test.ts +++ b/packages/nodes-base/nodes/Aws/S3/test/V2/AwsS3.node.test.ts @@ -1,11 +1,8 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../__tests__/credentials'; -const workflows = getWorkflowFilenames(__dirname); - describe('Test S3 V2 Node', () => { describe('File Upload', () => { let mock: nock.Scope; @@ -39,6 +36,6 @@ describe('Test S3 V2 Node', () => { .reply(200, { success: true }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/Aws/SES/test/AwsSes.node.test.ts b/packages/nodes-base/nodes/Aws/SES/test/AwsSes.node.test.ts index 7d626ed4b6..7b6ec38dd7 100644 --- a/packages/nodes-base/nodes/Aws/SES/test/AwsSes.node.test.ts +++ b/packages/nodes-base/nodes/Aws/SES/test/AwsSes.node.test.ts @@ -1,13 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow'; import assert from 'node:assert'; import qs from 'node:querystring'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - import { credentials } from '../../__tests__/credentials'; describe('AwsSes Node', () => { + const testHarness = new NodeTestHarness(); const email = 'test+user@example.com'; const templateData = { Name: 'Special. Characters @#$%^&*()_-', @@ -65,7 +64,6 @@ describe('AwsSes Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'AWS SES': [[{ json: { success: 'true' } }]], }, @@ -153,7 +151,6 @@ describe('AwsSes Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'AWS SES': [[{ json: { success: 'true' } }]] }, }, nock: { @@ -171,13 +168,7 @@ describe('AwsSes Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - testData.credentials = credentials; - const { result } = await executeWorkflow(testData); - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.finished).toEqual(true); - }); + for (const testData of tests) { + testHarness.setupTest(testData, { credentials }); + } }); diff --git a/packages/nodes-base/nodes/Baserow/__tests__/workflow/workflow.test.ts b/packages/nodes-base/nodes/Baserow/__tests__/workflow/workflow.test.ts index 35583711a5..57506d32c4 100644 --- a/packages/nodes-base/nodes/Baserow/__tests__/workflow/workflow.test.ts +++ b/packages/nodes-base/nodes/Baserow/__tests__/workflow/workflow.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { createResponse, fieldsResponse, @@ -55,7 +54,6 @@ describe('Baserow > Workflows', () => { mock.delete('/api/database/rows/table/482710/3/').reply(200, {}); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/Code/test/Code.node.test.ts b/packages/nodes-base/nodes/Code/test/Code.node.test.ts index 2953098c03..ffd60e3656 100644 --- a/packages/nodes-base/nodes/Code/test/Code.node.test.ts +++ b/packages/nodes-base/nodes/Code/test/Code.node.test.ts @@ -1,18 +1,15 @@ import { NodeVM } from '@n8n/vm2'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { anyNumber, mock } from 'jest-mock-extended'; import { normalizeItems } from 'n8n-core'; import type { IExecuteFunctions, IWorkflowDataProxyData } from 'n8n-workflow'; import { ApplicationError } from 'n8n-workflow'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { Code } from '../Code.node'; import { ValidationError } from '../ValidationError'; describe('Test Code Node', () => { - const workflows = getWorkflowFilenames(__dirname); - - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); describe('Code Node unit test', () => { diff --git a/packages/nodes-base/nodes/CompareDatasets/test/node/CompareDatasets.test.ts b/packages/nodes-base/nodes/CompareDatasets/test/node/CompareDatasets.test.ts index 36b48febcc..e6ee276593 100644 --- a/packages/nodes-base/nodes/CompareDatasets/test/node/CompareDatasets.test.ts +++ b/packages/nodes-base/nodes/CompareDatasets/test/node/CompareDatasets.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Compare Datasets Node', () => testWorkflows(workflows)); +describe('Test Compare Datasets Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Compression/test/node/Compression.test.ts b/packages/nodes-base/nodes/Compression/test/node/Compression.test.ts index 314662b2a1..d4cd694897 100644 --- a/packages/nodes-base/nodes/Compression/test/node/Compression.test.ts +++ b/packages/nodes-base/nodes/Compression/test/node/Compression.test.ts @@ -1,16 +1,14 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ -import type { IDataObject, WorkflowTestData } from 'n8n-workflow'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; +import type { WorkflowTestData } from 'n8n-workflow'; import os from 'node:os'; import path from 'path'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import { getResultNodeData, readJsonFileSync } from '@test/nodes/Helpers'; - if (os.platform() !== 'win32') { describe('Execute Compression Node', () => { - const workflowData = readJsonFileSync('nodes/Compression/test/node/workflow.compression.json'); + const testHarness = new NodeTestHarness(); + const workflowData = testHarness.readWorkflowJSON('workflow.compression.json'); - const node = workflowData.nodes.find((n: IDataObject) => n.name === 'Read Binary File'); + const node = workflowData.nodes.find((n) => n.name === 'Read Binary File')!; node.parameters.filePath = path.join(__dirname, 'lorem.txt'); const tests: WorkflowTestData[] = [ @@ -20,6 +18,7 @@ if (os.platform() !== 'win32') { workflowData, }, output: { + assertBinaryData: true, nodeData: { Compression1: [ [ @@ -44,16 +43,7 @@ if (os.platform() !== 'win32') { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => { - expect(resultData).toEqual(testData.output.nodeData[nodeName]); - }); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); } else { diff --git a/packages/nodes-base/nodes/Crypto/test/Crypto.test.ts b/packages/nodes-base/nodes/Crypto/test/Crypto.test.ts index c47efaf073..966aeb69e7 100644 --- a/packages/nodes-base/nodes/Crypto/test/Crypto.test.ts +++ b/packages/nodes-base/nodes/Crypto/test/Crypto.test.ts @@ -1,11 +1,8 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import fs from 'fs'; import fsPromises from 'fs/promises'; import { Readable } from 'stream'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - -const workflows = getWorkflowFilenames(__dirname); - describe('Test Crypto Node', () => { jest.mock('fast-glob', () => async () => ['/test/binary.data']); jest.mock('fs/promises'); @@ -13,5 +10,5 @@ describe('Test Crypto Node', () => { jest.mock('fs'); fs.createReadStream = () => Readable.from(Buffer.from('test')) as fs.ReadStream; - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/DateTime/test/node/DateTime.test.ts b/packages/nodes-base/nodes/DateTime/test/node/DateTime.test.ts index 6c98039b78..58b87df4bb 100644 --- a/packages/nodes-base/nodes/DateTime/test/node/DateTime.test.ts +++ b/packages/nodes-base/nodes/DateTime/test/node/DateTime.test.ts @@ -1,16 +1,13 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import moment from 'moment-timezone'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - -const workflows = getWorkflowFilenames(__dirname); - -// ! When making changes to the Workflow test files make sure to export env TZ=UTC as Github Actions runs in UTC timezone -if (new Date().getTimezoneOffset() === 0 || moment().utcOffset() === 0) { - describe('Test DateTime Node', () => testWorkflows(workflows)); -} else { - describe('Test DateTime Node', () => { +describe('Test DateTime Node', () => { + // ! When making changes to the Workflow test files make sure to export env TZ=UTC as Github Actions runs in UTC timezone + if (new Date().getTimezoneOffset() === 0 || moment().utcOffset() === 0) { + new NodeTestHarness().setupTests(); + } else { it('Skipped because timezone is not UTC', () => { expect(true).toBe(true); }); - }); -} + } +}); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/channel/create.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/channel/create.test.ts index 20088d7a9c..f6672f347d 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/channel/create.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/channel/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, channel => create', () => { nock('https://discord.com/api/v10') .post('/guilds/1168516062791340136/channels', { name: 'third', type: '0' }) @@ -20,6 +19,7 @@ describe('Test DiscordV2, channel => create', () => { nsfw: false, }); - const workflows = ['nodes/Discord/test/v2/node/channel/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/channel/deleteChannel.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/channel/deleteChannel.test.ts index 5e4849f9b8..a412d55e13 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/channel/deleteChannel.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/channel/deleteChannel.test.ts @@ -1,12 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - 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']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['deleteChannel.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/channel/get.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/channel/get.test.ts index e8768e2039..4890ce29e9 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/channel/get.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/channel/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, channel => get', () => { nock('https://discord.com/api/v10') .persist() @@ -23,6 +22,7 @@ describe('Test DiscordV2, channel => get', () => { nsfw: false, }); - const workflows = ['nodes/Discord/test/v2/node/channel/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/channel/getAll.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/channel/getAll.test.ts index 2b8b58bc9e..d2cc33b589 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/channel/getAll.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/channel/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, channel => getAll', () => { nock('https://discord.com/api/v10') .get('/guilds/1168516062791340136/channels') @@ -96,6 +95,7 @@ describe('Test DiscordV2, channel => getAll', () => { }, ]); - const workflows = ['nodes/Discord/test/v2/node/channel/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/channel/update.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/channel/update.test.ts index 2a8c83fac3..e4c6d2a9c0 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/channel/update.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/channel/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, channel => update', () => { nock('https://discord.com/api/v10').patch('/channels/1168516240332034067').reply(200, { id: '1168516240332034067', @@ -18,6 +17,7 @@ describe('Test DiscordV2, channel => update', () => { nsfw: true, }); - const workflows = ['nodes/Discord/test/v2/node/channel/update.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/member/getAll.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/member/getAll.test.ts index 89473586c7..704014cccf 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/member/getAll.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/member/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, member => getAll', () => { nock('https://discord.com/api/v10') .get('/guilds/1168516062791340136/members?limit=2') @@ -43,6 +42,7 @@ describe('Test DiscordV2, member => getAll', () => { }, ]); - const workflows = ['nodes/Discord/test/v2/node/member/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/member/roleAdd.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/member/roleAdd.test.ts index 5d0bbd2ff5..7f9a260165 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/member/roleAdd.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/member/roleAdd.test.ts @@ -1,12 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - 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']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['roleAdd.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/member/roleRemove.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/member/roleRemove.test.ts index 6fe2ea8bca..61edfcb60f 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/member/roleRemove.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/member/roleRemove.test.ts @@ -1,13 +1,13 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - 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']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['roleRemove.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/message/deleteMessage.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/message/deleteMessage.test.ts index 2aea6c7f48..c4cd032d48 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/message/deleteMessage.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/message/deleteMessage.test.ts @@ -1,12 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - 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']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['deleteMessage.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/message/get.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/message/get.test.ts index 25c0d321f0..674425bdd3 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/message/get.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/message/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, message => get', () => { nock('https://discord.com/api/v10') .get('/channels/1168516240332034067/messages/1168777380144369718') @@ -28,6 +27,7 @@ describe('Test DiscordV2, message => get', () => { type: 0, }); - const workflows = ['nodes/Discord/test/v2/node/message/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/message/getAll.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/message/getAll.test.ts index a98b995c99..70cc0f8db5 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/message/getAll.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/message/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, message => getAll', () => { nock('https://discord.com/api/v10') .get('/channels/1168516240332034067/messages?limit=1') @@ -51,6 +50,7 @@ describe('Test DiscordV2, message => getAll', () => { }, ]); - const workflows = ['nodes/Discord/test/v2/node/message/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/message/react.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/message/react.test.ts index 1823ca0858..66605b1776 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/message/react.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/message/react.test.ts @@ -1,12 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - 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']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['react.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/message/send.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/message/send.test.ts index 8757806170..a5e1fb4595 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/message/send.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/message/send.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, message => send', () => { nock('https://discord.com/api/v10') .post('/channels/1168516240332034067/messages', { @@ -61,6 +60,7 @@ describe('Test DiscordV2, message => send', () => { referenced_message: null, }); - const workflows = ['nodes/Discord/test/v2/node/message/send.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['send.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Discord/test/v2/node/webhook/sendLegacy.test.ts b/packages/nodes-base/nodes/Discord/test/v2/node/webhook/sendLegacy.test.ts index c5a158f2b8..8c698cc609 100644 --- a/packages/nodes-base/nodes/Discord/test/v2/node/webhook/sendLegacy.test.ts +++ b/packages/nodes-base/nodes/Discord/test/v2/node/webhook/sendLegacy.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test DiscordV2, webhook => sendLegacy', () => { const credentials = { discordWebhookApi: { @@ -50,6 +49,8 @@ describe('Test DiscordV2, webhook => sendLegacy', () => { webhook_id: '1153265494955135077', }); - const workflows = ['nodes/Discord/test/v2/node/webhook/sendLegacy.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['sendLegacy.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/EvaluationMetrics/EvaluationMetrics.node.test.ts b/packages/nodes-base/nodes/EvaluationMetrics/__tests__/EvaluationMetrics.node.test.ts similarity index 97% rename from packages/nodes-base/nodes/EvaluationMetrics/EvaluationMetrics.node.test.ts rename to packages/nodes-base/nodes/EvaluationMetrics/__tests__/EvaluationMetrics.node.test.ts index 9d5e215520..40462c5925 100644 --- a/packages/nodes-base/nodes/EvaluationMetrics/EvaluationMetrics.node.test.ts +++ b/packages/nodes-base/nodes/EvaluationMetrics/__tests__/EvaluationMetrics.node.test.ts @@ -2,7 +2,7 @@ import { mock } from 'jest-mock-extended'; import type { INodeTypes, IExecuteFunctions, AssignmentCollectionValue } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow'; -import { EvaluationMetrics } from './EvaluationMetrics.node'; +import { EvaluationMetrics } from '../EvaluationMetrics.node'; describe('EvaluationMetrics Node', () => { const nodeTypes = mock(); diff --git a/packages/nodes-base/nodes/ExecuteCommand/test/ExecuteCommand.node.test.ts b/packages/nodes-base/nodes/ExecuteCommand/test/ExecuteCommand.node.test.ts index bde43182f1..a8a95780c0 100644 --- a/packages/nodes-base/nodes/ExecuteCommand/test/ExecuteCommand.node.test.ts +++ b/packages/nodes-base/nodes/ExecuteCommand/test/ExecuteCommand.node.test.ts @@ -1,4 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; -const workflows = getWorkflowFilenames(__dirname); +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -describe('Execute Execute Command Node', () => testWorkflows(workflows)); +describe('Execute Execute Command Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/ExecutionData/test/ExecutionData.node.test.ts b/packages/nodes-base/nodes/ExecutionData/test/ExecutionData.node.test.ts index 25c361eca7..c0a347fc42 100644 --- a/packages/nodes-base/nodes/ExecutionData/test/ExecutionData.node.test.ts +++ b/packages/nodes-base/nodes/ExecutionData/test/ExecutionData.node.test.ts @@ -1,8 +1,7 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { mock } from 'jest-mock-extended'; import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { ExecutionData } from '../ExecutionData.node'; describe('ExecutionData Node', () => { @@ -20,5 +19,6 @@ describe('ExecutionData Node', () => { }); }); -const workflows = getWorkflowFilenames(__dirname); -describe('ExecutionData -> Should run the workflow', () => testWorkflows(workflows)); +describe('ExecutionData -> Should run the workflow', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Files/ConvertToFile/test/ConvertToFile.node.test.ts b/packages/nodes-base/nodes/Files/ConvertToFile/test/ConvertToFile.node.test.ts index ca8993a8f8..6aa474d057 100644 --- a/packages/nodes-base/nodes/Files/ConvertToFile/test/ConvertToFile.node.test.ts +++ b/packages/nodes-base/nodes/Files/ConvertToFile/test/ConvertToFile.node.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test ConvertToFile Node', () => testWorkflows(workflows)); +describe('Test ConvertToFile Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Files/ExtractFromFile/test/ExtractFromFile.node.test.ts b/packages/nodes-base/nodes/Files/ExtractFromFile/test/ExtractFromFile.node.test.ts index aebf28eb73..914927025f 100644 --- a/packages/nodes-base/nodes/Files/ExtractFromFile/test/ExtractFromFile.node.test.ts +++ b/packages/nodes-base/nodes/Files/ExtractFromFile/test/ExtractFromFile.node.test.ts @@ -1,6 +1,5 @@ -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; describe('ExtractFromFile', () => { - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts b/packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts index d46c3ef648..89396660e4 100644 --- a/packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts +++ b/packages/nodes-base/nodes/Files/ReadWriteFile/actions/read.operation.ts @@ -124,7 +124,6 @@ export async function execute(this: IExecuteFunctions, items: INodeExecutionData mimeType: binaryData.mimeType, fileType: binaryData.fileType, fileName: binaryData.fileName, - directory: binaryData.directory, fileExtension: binaryData.fileExtension, fileSize: binaryData.fileSize, }, diff --git a/packages/nodes-base/nodes/Files/ReadWriteFile/test/ReadWriteFile.test.ts b/packages/nodes-base/nodes/Files/ReadWriteFile/test/ReadWriteFile.test.ts index a86838fad0..0687b67e66 100644 --- a/packages/nodes-base/nodes/Files/ReadWriteFile/test/ReadWriteFile.test.ts +++ b/packages/nodes-base/nodes/Files/ReadWriteFile/test/ReadWriteFile.test.ts @@ -1,36 +1,31 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Test ReadWriteFile Node', () => { - const temporaryDir = Helpers.createTemporaryDir(); const directory = __dirname.replace(/\\/gi, '/'); - const workflow = Helpers.readJsonFileSync( - 'nodes/Files/ReadWriteFile/test/ReadWriteFile.workflow.json', - ); + const testHarness = new NodeTestHarness(); + const workflowData = testHarness.readWorkflowJSON('ReadWriteFile.workflow.json'); - const readFileNode = workflow.nodes.find((n: any) => n.name === 'Read from Disk'); + const readFileNode = workflowData.nodes.find((n) => n.name === 'Read from Disk')!; readFileNode.parameters.fileSelector = `${directory}/image.jpg`; - const writeFileNode = workflow.nodes.find((n: any) => n.name === 'Write to Disk'); - writeFileNode.parameters.fileName = `${temporaryDir}/image-written.jpg`; + const writeFileNode = workflowData.nodes.find((n) => n.name === 'Write to Disk')!; + writeFileNode.parameters.fileName = `${testHarness.temporaryDir}/image-written.jpg`; const tests: WorkflowTestData[] = [ { description: 'nodes/Files/ReadWriteFile/test/ReadWriteFile.workflow.json', input: { - workflowData: workflow, + workflowData, }, output: { + assertBinaryData: true, nodeData: { 'Read from Disk': [ [ { json: { - directory, fileExtension: 'jpg', fileName: 'image.jpg', fileSize: '1.04 kB', @@ -43,7 +38,6 @@ describe('Test ReadWriteFile Node', () => { fileType: 'image', fileExtension: 'jpg', data: '/9j/4AAQSkZJRgABAQEASABIAAD/4QBmRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAAQAAAATgAAAAAAARlJAAAD6AABGUkAAAPocGFpbnQubmV0IDUuMC4xAP/bAEMAIBYYHBgUIBwaHCQiICYwUDQwLCwwYkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxv/bAEMBIiQkMCowXjQ0XsaEcITGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxv/AABEIAB8AOwMBEgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOgqgrXF2zNHJ5aKcD3oNPZ23di/VKG82bkuTh1OMgdaAdOSLtZ6G5ut0iSeWoOAKAdO27NCqUN8oQrcHDqccDrQDpyRNPdRwEKcsx7CobIebPLORwThc0inGMF724jagNpxG4OOM1dIDAgjIPBpkqUOxnR2pmh85pW3nJB9KkNi4yqTssZ6rSNXNX0ehHFfusYDLuI7+tXY4I40ChQcdzQRKcL7Fb7PcQO32cqUY5we1XqZPtH11KsFoFDGYK7sckkZxVqgTnJlEQXMBZYGUoTkZ7VeoH7RvcqwWaIh80K7k5JIq1QJzkyhbMtvdSxMdqnlc1amgjmx5i5I70inNSVpFdrmaWRltkBVerHvUW57B2AUNGxyOaC+VW9xXLVrcGbcjrtkXqKZZxvveeTAL9APSgiooq1ty3RTMj//2Q==', - directory, fileName: 'image.jpg', fileSize: '1.04 kB', }, @@ -55,7 +49,6 @@ describe('Test ReadWriteFile Node', () => { [ { json: { - directory, fileExtension: 'jpg', fileName: writeFileNode.parameters.fileName, fileSize: '1.04 kB', @@ -68,7 +61,6 @@ describe('Test ReadWriteFile Node', () => { fileType: 'image', fileExtension: 'jpg', data: '/9j/4AAQSkZJRgABAQEASABIAAD/4QBmRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAAQAAAATgAAAAAAARlJAAAD6AABGUkAAAPocGFpbnQubmV0IDUuMC4xAP/bAEMAIBYYHBgUIBwaHCQiICYwUDQwLCwwYkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxv/bAEMBIiQkMCowXjQ0XsaEcITGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxv/AABEIAB8AOwMBEgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOgqgrXF2zNHJ5aKcD3oNPZ23di/VKG82bkuTh1OMgdaAdOSLtZ6G5ut0iSeWoOAKAdO27NCqUN8oQrcHDqccDrQDpyRNPdRwEKcsx7CobIebPLORwThc0inGMF724jagNpxG4OOM1dIDAgjIPBpkqUOxnR2pmh85pW3nJB9KkNi4yqTssZ6rSNXNX0ehHFfusYDLuI7+tXY4I40ChQcdzQRKcL7Fb7PcQO32cqUY5we1XqZPtH11KsFoFDGYK7sckkZxVqgTnJlEQXMBZYGUoTkZ7VeoH7RvcqwWaIh80K7k5JIq1QJzkyhbMtvdSxMdqnlc1amgjmx5i5I70inNSVpFdrmaWRltkBVerHvUW57B2AUNGxyOaC+VW9xXLVrcGbcjrtkXqKZZxvveeTAL9APSgiooq1ty3RTMj//2Q==', - directory, fileName: 'image.jpg', fileSize: '1.04 kB', }, @@ -82,15 +74,6 @@ describe('Test ReadWriteFile Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => { - expect(resultData).toEqual(testData.output.nodeData[nodeName]); - }); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/Files/test/ConvertExtract.test.ts b/packages/nodes-base/nodes/Files/test/ConvertExtract.test.ts index 9ff4604263..f0daf42a43 100644 --- a/packages/nodes-base/nodes/Files/test/ConvertExtract.test.ts +++ b/packages/nodes-base/nodes/Files/test/ConvertExtract.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Convert to File Node', () => testWorkflows(workflows)); +describe('Test Convert to File Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Filter/test/Filter.node.test.ts b/packages/nodes-base/nodes/Filter/test/Filter.node.test.ts index 218ced5f51..f2d525b90c 100644 --- a/packages/nodes-base/nodes/Filter/test/Filter.node.test.ts +++ b/packages/nodes-base/nodes/Filter/test/Filter.node.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Filter Node', () => testWorkflows(workflows)); +describe('Test Filter Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Form/utils.ts b/packages/nodes-base/nodes/Form/utils.ts index 4c8f879882..ab9b4a4b00 100644 --- a/packages/nodes-base/nodes/Form/utils.ts +++ b/packages/nodes-base/nodes/Form/utils.ts @@ -83,7 +83,7 @@ export const prepareFormFields = (context: IWebhookFunctions, fields: FormFields html = html.replace(resolvable, context.evaluateExpression(resolvable) as string); } - field.html = sanitizeHtml(html as string); + field.html = sanitizeHtml(html); } if (field.fieldType === 'hiddenField') { diff --git a/packages/nodes-base/nodes/Github/__tests__/node/Github.dispatchAndWait.node.test.ts b/packages/nodes-base/nodes/Github/__tests__/node/Github.dispatchAndWait.node.test.ts index 33eaa20d27..d55db63efd 100644 --- a/packages/nodes-base/nodes/Github/__tests__/node/Github.dispatchAndWait.node.test.ts +++ b/packages/nodes-base/nodes/Github/__tests__/node/Github.dispatchAndWait.node.test.ts @@ -1,11 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - -const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('GithubDispatchAndWaitWorkflow.json'), -); - describe('Test Github Node - Dispatch and Wait', () => { describe('Workflow Dispatch and Wait', () => { const now = 1683028800000; @@ -77,7 +72,7 @@ describe('Test Github Node - Dispatch and Wait', () => { .post( `/repos/${owner}/${repository}/actions/workflows/${workflowId}/dispatches`, (body) => { - return body.ref === ref && body.inputs && body.inputs.resumeUrl; + return body.ref === ref && body.inputs?.resumeUrl; }, ) .reply(200, {}); @@ -87,6 +82,8 @@ describe('Test Github Node - Dispatch and Wait', () => { nock.cleanAll(); }); - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['GithubDispatchAndWaitWorkflow.json'], + }); }); }); diff --git a/packages/nodes-base/nodes/Github/__tests__/node/Github.node.test.ts b/packages/nodes-base/nodes/Github/__tests__/node/Github.node.test.ts index a87694155a..7eb32dfd87 100644 --- a/packages/nodes-base/nodes/Github/__tests__/node/Github.node.test.ts +++ b/packages/nodes-base/nodes/Github/__tests__/node/Github.node.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { NodeApiError, NodeOperationError } from 'n8n-workflow'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { Github } from '../../Github.node'; -const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('GithubTestWorkflow.json'), -); - describe('Test Github Node', () => { describe('Workflow Dispatch', () => { const now = 1683028800000; @@ -87,7 +82,9 @@ describe('Test Github Node', () => { .reply(200, {}); }); - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['GithubTestWorkflow.json'], + }); }); describe('Error Handling', () => { diff --git a/packages/nodes-base/nodes/Gong/test/Gong.node.test.ts b/packages/nodes-base/nodes/Gong/test/Gong.node.test.ts index 4c1724c869..9ea94ce407 100644 --- a/packages/nodes-base/nodes/Gong/test/Gong.node.test.ts +++ b/packages/nodes-base/nodes/Gong/test/Gong.node.test.ts @@ -1,12 +1,11 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import { NodeConnectionTypes } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - import { gongApiResponse, gongNodeResponse } from './mocks'; describe('Gong Node', () => { + const testHarness = new NodeTestHarness(); const baseUrl = 'https://api.gong.io'; const credentials = { gongApi: { baseUrl }, @@ -103,7 +102,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Gong gongApi': [[{ json: { metaData: gongNodeResponse.getCall[0].json.metaData } }]], 'Gong gongOAuth2Api': [ @@ -141,15 +139,9 @@ describe('Gong Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - testData.credentials = credentials; - const { result } = await executeWorkflow(testData); - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.finished).toEqual(true); - }); + for (const testData of tests) { + testHarness.setupTest(testData, { credentials }); + } }); describe('Call description', () => { @@ -207,7 +199,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [[{ json: { metaData: gongNodeResponse.getCall[0].json.metaData } }]], }, @@ -298,7 +289,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [gongNodeResponse.getCall], }, @@ -415,7 +405,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [gongNodeResponse.getAllCall], }, @@ -552,7 +541,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [ Array.from({ length: 50 }, () => ({ ...gongNodeResponse.getAllCallNoOptions[0] })), @@ -633,7 +621,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [[{ json: {} }]], }, @@ -709,10 +696,10 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [], }, + error: 'The resource you are requesting could not be found', }, nock: { baseUrl, @@ -736,24 +723,9 @@ describe('Gong Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - testData.credentials = credentials; - const { result } = await executeWorkflow(testData); - - if (testData.description === 'should handle error response') { - // Only matches error message - expect(() => Helpers.getResultNodeData(result, testData)).toThrowError( - 'The resource you are requesting could not be found', - ); - return; - } - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.finished).toEqual(true); - }); + for (const testData of tests) { + testHarness.setupTest(testData, { credentials }); + } }); describe('User description', () => { @@ -810,7 +782,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [gongNodeResponse.getUser], }, @@ -885,7 +856,6 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [gongNodeResponse.getAllUser], }, @@ -979,10 +949,10 @@ describe('Gong Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Gong: [], }, + error: "The Users IDs don't match any existing user", }, nock: { baseUrl, @@ -1006,22 +976,8 @@ describe('Gong Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - testData.credentials = credentials; - const { result } = await executeWorkflow(testData); - - if (testData.description === 'should handle error response') { - expect(() => Helpers.getResultNodeData(result, testData)).toThrow( - "The Users IDs don't match any existing user", - ); - return; - } - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.finished).toEqual(true); - }); + for (const testData of tests) { + testHarness.setupTest(testData, { credentials }); + } }); }); diff --git a/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/executeQuery.test.ts b/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/executeQuery.test.ts index ba3559430e..4d2a1e91a5 100644 --- a/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/executeQuery.test.ts +++ b/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/executeQuery.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - jest.mock('jsonwebtoken', () => ({ sign: jest.fn().mockReturnValue('signature'), })); @@ -37,6 +36,7 @@ describe('Test Google BigQuery V2, executeQuery', () => { .get('/v2/projects/test-project/queries/job_123?maxResults=1000&timeoutMs=10000') .reply(200, { rows: [], schema: {} }); - const workflows = ['nodes/Google/BigQuery/test/v2/node/executeQuery.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['executeQuery.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.test.ts b/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.test.ts index f7b0cd3dae..cf0a172475 100644 --- a/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.test.ts +++ b/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - jest.mock('jsonwebtoken', () => ({ sign: jest.fn().mockReturnValue('signature'), })); @@ -42,6 +41,7 @@ describe('Test Google BigQuery V2, insert auto map', () => { { kind: 'bigquery#tableDataInsertAllResponse' }, ]); - const workflows = ['nodes/Google/BigQuery/test/v2/node/insert.autoMapMode.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['insert.autoMapMode.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.manualMode.test.ts b/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.manualMode.test.ts index 91bead8485..4d7a8bc0c5 100644 --- a/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.manualMode.test.ts +++ b/packages/nodes-base/nodes/Google/BigQuery/test/v2/node/insert.manualMode.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - jest.mock('jsonwebtoken', () => ({ sign: jest.fn().mockReturnValue('signature'), })); @@ -35,6 +34,7 @@ describe('Test Google BigQuery V2, insert define manually', () => { ) .reply(200, [{ kind: 'bigquery#tableDataInsertAllResponse' }]); - const workflows = ['nodes/Google/BigQuery/test/v2/node/insert.manualMode.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['insert.manualMode.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Google/Gmail/test/v1/GmailV1.node.test.ts b/packages/nodes-base/nodes/Google/Gmail/test/v1/GmailV1.node.test.ts index d134067539..d98a0c13b5 100644 --- a/packages/nodes-base/nodes/Google/Gmail/test/v1/GmailV1.node.test.ts +++ b/packages/nodes-base/nodes/Google/Gmail/test/v1/GmailV1.node.test.ts @@ -1,9 +1,8 @@ /* eslint-disable n8n-nodes-base/node-param-display-name-miscased */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { jsonParse } from 'n8n-workflow'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import labels from '../fixtures/labels.json'; import messages from '../fixtures/messages.json'; @@ -71,7 +70,9 @@ describe('Test Gmail Node v1', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v1/messages.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['messages.workflow.json'], + }); }); describe('Labels', () => { @@ -94,7 +95,9 @@ describe('Test Gmail Node v1', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v1/labels.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['labels.workflow.json'], + }); }); describe('Message Labels', () => { @@ -111,7 +114,9 @@ describe('Test Gmail Node v1', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v1/message-labels.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['message-labels.workflow.json'], + }); }); describe('Drafts', () => { @@ -189,6 +194,8 @@ describe('Test Gmail Node v1', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v1/drafts.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['drafts.workflow.json'], + }); }); }); diff --git a/packages/nodes-base/nodes/Google/Gmail/test/v2/GmailV2.node.test.ts b/packages/nodes-base/nodes/Google/Gmail/test/v2/GmailV2.node.test.ts index 8cdf033db5..abd758b56c 100644 --- a/packages/nodes-base/nodes/Google/Gmail/test/v2/GmailV2.node.test.ts +++ b/packages/nodes-base/nodes/Google/Gmail/test/v2/GmailV2.node.test.ts @@ -1,10 +1,9 @@ /* eslint-disable n8n-nodes-base/node-param-display-name-miscased */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { mock, mockDeep } from 'jest-mock-extended'; import { jsonParse, type ILoadOptionsFunctions, type INode } from 'n8n-workflow'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { getGmailAliases, getLabels, getThreadMessages } from '../../v2/loadOptions'; import labels from '../fixtures/labels.json'; import messages from '../fixtures/messages.json'; @@ -131,7 +130,9 @@ describe('Test Gmail Node v2', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v2/messages.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['messages.workflow.json'], + }); }); describe('Labels', () => { @@ -154,7 +155,9 @@ describe('Test Gmail Node v2', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v2/labels.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['labels.workflow.json'], + }); }); describe('Drafts', () => { @@ -242,7 +245,9 @@ describe('Test Gmail Node v2', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v2/drafts.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['drafts.workflow.json'], + }); }); describe('Threads', () => { @@ -303,7 +308,9 @@ describe('Test Gmail Node v2', () => { afterAll(() => gmailNock.done()); - testWorkflows(['nodes/Google/Gmail/test/v2/threads.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['threads.workflow.json'], + }); }); describe('loadOptions', () => { diff --git a/packages/nodes-base/nodes/Google/YouTube/__test__/node/YouTube.node.test.ts b/packages/nodes-base/nodes/Google/YouTube/__test__/node/YouTube.node.test.ts index 428792b856..500908dab0 100644 --- a/packages/nodes-base/nodes/Google/YouTube/__test__/node/YouTube.node.test.ts +++ b/packages/nodes-base/nodes/Google/YouTube/__test__/node/YouTube.node.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import categories from './fixtures/categories.json'; import channels from './fixtures/channels.json'; import playlistItems from './fixtures/playlistItems.json'; @@ -62,9 +61,10 @@ describe('Test YouTube Node', () => { }); }); - afterAll(() => youtubeNock.done()); - - testWorkflows(['nodes/Google/YouTube/__test__/node/channels.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['channels.workflow.json'], + }); }); describe('Playlist', () => { @@ -113,9 +113,10 @@ describe('Test YouTube Node', () => { youtubeNock.delete('/v3/playlists', { id: 'playlist_id_1' }).reply(200, { success: true }); }); - afterAll(() => youtubeNock.done()); - - testWorkflows(['nodes/Google/YouTube/__test__/node/playlists.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['playlists.workflow.json'], + }); }); describe('Video Categories', () => { @@ -131,10 +132,10 @@ describe('Test YouTube Node', () => { afterAll(() => youtubeNock.done()); - testWorkflows( - ['nodes/Google/YouTube/__test__/node/videoCategories.workflow.json'], + new NodeTestHarness().setupTests({ credentials, - ); + workflowFiles: ['videoCategories.workflow.json'], + }); }); describe('Playlist Item', () => { @@ -173,6 +174,9 @@ describe('Test YouTube Node', () => { afterAll(() => youtubeNock.done()); - testWorkflows(['nodes/Google/YouTube/__test__/node/playlistItems.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['playlistItems.workflow.json'], + }); }); }); diff --git a/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts b/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts index 1b097f64ae..bdae514921 100644 --- a/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts +++ b/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts @@ -1,8 +1,7 @@ /* eslint-disable n8n-nodes-base/node-filename-against-convention */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - describe('GraphQL Node', () => { const baseUrl = 'https://api.n8n.io/'; @@ -58,6 +57,5 @@ describe('GraphQL Node', () => { }); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/Html/test/Html.node.test.ts b/packages/nodes-base/nodes/Html/test/Html.node.test.ts index 9fc798c198..3711b1be5e 100644 --- a/packages/nodes-base/nodes/Html/test/Html.node.test.ts +++ b/packages/nodes-base/nodes/Html/test/Html.node.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Html Node > extractHtmlContent', () => testWorkflows(workflows)); +describe('Test Html Node > extractHtmlContent', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/HtmlExtract/test/HtmlExtract.node.test.ts b/packages/nodes-base/nodes/HtmlExtract/test/HtmlExtract.node.test.ts index ef08ff6a28..e6e663d9bb 100644 --- a/packages/nodes-base/nodes/HtmlExtract/test/HtmlExtract.node.test.ts +++ b/packages/nodes-base/nodes/HtmlExtract/test/HtmlExtract.node.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test HTML Extract Node', () => testWorkflows(workflows)); +describe('Test HTML Extract Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/HttpRequest/test/binaryData/HttpRequest.test.ts b/packages/nodes-base/nodes/HttpRequest/test/binaryData/HttpRequest.test.ts index 5059df6537..5896beb189 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/binaryData/HttpRequest.test.ts +++ b/packages/nodes-base/nodes/HttpRequest/test/binaryData/HttpRequest.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - describe('Test Binary Data Download', () => { const baseUrl = 'https://dummy.domain'; @@ -21,6 +20,5 @@ describe('Test Binary Data Download', () => { }); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests({ assertBinaryData: true }); }); diff --git a/packages/nodes-base/nodes/HttpRequest/test/binaryData/binaryData.test.json b/packages/nodes-base/nodes/HttpRequest/test/binaryData/binaryData.test.json index 5e1cc9496a..cf04374320 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/binaryData/binaryData.test.json +++ b/packages/nodes-base/nodes/HttpRequest/test/binaryData/binaryData.test.json @@ -6,10 +6,7 @@ "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "parameters": {}, - "position": [ - 580, - 300 - ] + "position": [580, 300] }, { "name": "HTTP Request (v1)", @@ -19,10 +16,7 @@ "url": "https://dummy.domain/path/to/image.png", "responseFormat": "file" }, - "position": [ - 1020, - -100 - ] + "position": [1020, -100] }, { "name": "HTTP Request (v2)", @@ -33,10 +27,7 @@ "responseFormat": "file", "options": {} }, - "position": [ - 1020, - 80 - ] + "position": [1020, 80] }, { "name": "HTTP Request (v3)", @@ -52,10 +43,7 @@ } } }, - "position": [ - 1020, - 240 - ] + "position": [1020, 240] }, { "name": "HTTP Request (v4)", @@ -71,10 +59,7 @@ } } }, - "position": [ - 1020, - 400 - ] + "position": [1020, 400] }, { "name": "Follow Redirect", @@ -90,10 +75,7 @@ } } }, - "position": [ - 1020, - 560 - ] + "position": [1020, 560] }, { "name": "Content Disposition", @@ -109,10 +91,7 @@ } } }, - "position": [ - 1020, - 720 - ] + "position": [1020, 720] } ], "pinData": { @@ -120,6 +99,7 @@ { "binary": { "data": { + "data": "dGVzdA==", "mimeType": "image/png", "fileType": "image", "fileExtension": "png", @@ -134,6 +114,7 @@ { "binary": { "data": { + "data": "dGVzdA==", "mimeType": "image/png", "fileType": "image", "fileExtension": "png", @@ -148,6 +129,7 @@ { "binary": { "data": { + "data": "dGVzdA==", "mimeType": "image/png", "fileType": "image", "fileExtension": "png", @@ -162,6 +144,7 @@ { "binary": { "data": { + "data": "dGVzdA==", "mimeType": "image/png", "fileType": "image", "fileExtension": "png", @@ -176,6 +159,7 @@ { "binary": { "data": { + "data": "dGVzdA==", "mimeType": "image/png", "fileType": "image", "fileExtension": "png", @@ -190,6 +174,7 @@ { "binary": { "data": { + "data": "dGVzdGluZw==", "mimeType": "image/jpeg", "fileType": "image", "fileExtension": "jpg", diff --git a/packages/nodes-base/nodes/HttpRequest/test/encoding/HttpRequest.test.ts b/packages/nodes-base/nodes/HttpRequest/test/encoding/HttpRequest.test.ts index 0617f9913a..6034d06c57 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/encoding/HttpRequest.test.ts +++ b/packages/nodes-base/nodes/HttpRequest/test/encoding/HttpRequest.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - describe('Test Response Encoding', () => { const baseUrl = 'https://dummy.domain'; const payload = Buffer.from( @@ -16,6 +15,5 @@ describe('Test Response Encoding', () => { .reply(200, payload, { 'content-type': 'text/plain; charset=latin1' }); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/HttpRequest/test/encodingQuoted/HttpRequest.test.ts b/packages/nodes-base/nodes/HttpRequest/test/encodingQuoted/HttpRequest.test.ts index a6f7975788..f2bf69c840 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/encodingQuoted/HttpRequest.test.ts +++ b/packages/nodes-base/nodes/HttpRequest/test/encodingQuoted/HttpRequest.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - describe('Test Quoted Response Encoding', () => { const baseUrl = 'https://dummy.domain'; const payload = Buffer.from( @@ -16,6 +15,5 @@ describe('Test Quoted Response Encoding', () => { .reply(200, payload, { 'content-type': 'text/plain; charset="latin1"' }); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/HttpRequest/test/node/HttpRequest.test.ts b/packages/nodes-base/nodes/HttpRequest/test/node/HttpRequest.test.ts index aa05ae3fa0..e0292feedf 100644 --- a/packages/nodes-base/nodes/HttpRequest/test/node/HttpRequest.test.ts +++ b/packages/nodes-base/nodes/HttpRequest/test/node/HttpRequest.test.ts @@ -1,8 +1,7 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; import { parse as parseUrl } from 'url'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - describe('Test HTTP Request Node', () => { const baseUrl = 'https://dummyjson.com'; @@ -181,6 +180,5 @@ describe('Test HTTP Request Node', () => { }); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/Hubspot/__test__/Hubspot.node.test.ts b/packages/nodes-base/nodes/Hubspot/__test__/Hubspot.node.test.ts index 492f3aaa23..c0d5079bdf 100644 --- a/packages/nodes-base/nodes/Hubspot/__test__/Hubspot.node.test.ts +++ b/packages/nodes-base/nodes/Hubspot/__test__/Hubspot.node.test.ts @@ -1,8 +1,7 @@ /* eslint-disable n8n-nodes-base/node-param-display-name-miscased */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import companies from './fixtures/companies.json'; import companiesSearchResult from './fixtures/companies_search_result.json'; import contacts from './fixtures/contacts.json'; @@ -114,7 +113,9 @@ describe('Hubspot Node', () => { afterAll(() => hubspotNock.done()); - testWorkflows(['nodes/Hubspot/__test__/companies.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['companies.workflow.json'], + }); }); describe('contacts', () => { @@ -210,7 +211,9 @@ describe('Hubspot Node', () => { afterAll(() => hubspotNock.done()); - testWorkflows(['nodes/Hubspot/__test__/contacts.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['contacts.workflow.json'], + }); }); describe('deals', () => { @@ -255,6 +258,8 @@ describe('Hubspot Node', () => { afterAll(() => hubspotNock.done()); - testWorkflows(['nodes/Hubspot/__test__/deals.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['deals.workflow.json'], + }); }); }); diff --git a/packages/nodes-base/nodes/ICalendar/test/node/ICalendar.test.ts b/packages/nodes-base/nodes/ICalendar/test/node/ICalendar.test.ts index 37b752a510..5a1c8d2993 100644 --- a/packages/nodes-base/nodes/ICalendar/test/node/ICalendar.test.ts +++ b/packages/nodes-base/nodes/ICalendar/test/node/ICalendar.test.ts @@ -1,19 +1,28 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import { getResultNodeData, readJsonFileSync } from '@test/nodes/Helpers'; +jest.mock('ics', () => { + const ics = jest.requireActual('ics'); + return { + ...ics, + createEvent(attributes: any, cb: () => {}) { + attributes.uid = 'test-uid'; + attributes.timestamp = '20250424T135100Z'; + return ics.createEvent(attributes, cb); + }, + }; +}); describe('iCalendar Node', () => { - const workflowData = readJsonFileSync('nodes/ICalendar/test/node/workflow.iCalendar.json'); - + const testHarness = new NodeTestHarness(); const tests: WorkflowTestData[] = [ { description: 'nodes/ICalendar/test/node/workflow.iCalendar.json', input: { - workflowData, + workflowData: testHarness.readWorkflowJSON('workflow.iCalendar.json'), }, output: { + assertBinaryData: true, nodeData: { iCalendar: [ [ @@ -24,9 +33,9 @@ describe('iCalendar Node', () => { mimeType: 'text/calendar', fileType: 'text', fileExtension: 'ics', - data: 'QkVHSU46VkNBTEVOREFSDQpWRVJTSU9OOjIuMA0KQ0FMU0NBTEU6R1JFR09SSUFODQpQUk9ESUQ6YWRhbWdpYmJvbnMvaWNzDQpNRVRIT0Q6UFVCTElTSA0KWC1XUi1DQUxOQU1FOmRlZmF1bHQNClgtUFVCTElTSEVELVRUTDpQVDFIDQpCRUdJTjpWRVZFTlQNClVJRDpMWC1zckVYdkI1MXA1ZUxNS1gwTnkNClNVTU1BUlk6bmV3IGV2ZW50DQpEVFNUQU1QOjIwMjMwMjEwVDA5MzYwMFoNCkRUU1RBUlQ7VkFMVUU9REFURToyMDIzMDIyOA0KRFRFTkQ7VkFMVUU9REFURToyMDIzMDMwMQ0KQVRURU5ERUU7UlNWUD1GQUxTRTtDTj1QZXJzb246bWFpbHRvOnBlcnNvbjFAZW1haWwuY29tDQpFTkQ6VkVWRU5UDQpFTkQ6VkNBTEVOREFSDQo=', + data: 'QkVHSU46VkNBTEVOREFSDQpWRVJTSU9OOjIuMA0KQ0FMU0NBTEU6R1JFR09SSUFODQpQUk9ESUQ6YWRhbWdpYmJvbnMvaWNzDQpNRVRIT0Q6UFVCTElTSA0KWC1XUi1DQUxOQU1FOmRlZmF1bHQNClgtUFVCTElTSEVELVRUTDpQVDFIDQpCRUdJTjpWRVZFTlQNClVJRDp0ZXN0LXVpZA0KU1VNTUFSWTpuZXcgZXZlbnQNCkRUU1RBTVA6MjAyNTA0MjRUMTM1MTAwWg0KRFRTVEFSVDtWQUxVRT1EQVRFOjIwMjMwMjI3DQpEVEVORDtWQUxVRT1EQVRFOjIwMjMwMjI4DQpBVFRFTkRFRTtSU1ZQPUZBTFNFO0NOPVBlcnNvbjptYWlsdG86cGVyc29uMUBlbWFpbC5jb20NCkVORDpWRVZFTlQNCkVORDpWQ0FMRU5EQVINCg==', fileName: 'event.ics', - fileSize: '359 B', + fileSize: '346 B', }, }, }, @@ -38,25 +47,6 @@ describe('iCalendar Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => { - //@ts-ignore - expect(resultData[0][0].binary.data.data.length).toEqual( - testData.output.nodeData[nodeName][0][0].binary.data.data.length, - ); - - //uid every time would be different, so we need to delete it in order to compare objects - //@ts-ignore - delete resultData[0][0].binary.data.data; - delete testData.output.nodeData[nodeName][0][0].binary.data.data; - - expect(resultData).toEqual(testData.output.nodeData[nodeName]); - }); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/If/test/v1/If.node.test.ts b/packages/nodes-base/nodes/If/test/v1/If.node.test.ts index 3a74ca0c07..75bb1bb4ca 100644 --- a/packages/nodes-base/nodes/If/test/v1/If.node.test.ts +++ b/packages/nodes-base/nodes/If/test/v1/If.node.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test IF Node', () => testWorkflows(workflows)); +describe('Test IF Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/If/test/v2/IfV2.node.test.ts b/packages/nodes-base/nodes/If/test/v2/IfV2.node.test.ts index e21f877091..0ca35ee1a2 100644 --- a/packages/nodes-base/nodes/If/test/v2/IfV2.node.test.ts +++ b/packages/nodes-base/nodes/If/test/v2/IfV2.node.test.ts @@ -1,3 +1,4 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { mock } from 'jest-mock-extended'; import { get } from 'lodash'; import { @@ -8,8 +9,6 @@ import { type IGetNodeParameterOptions, } from 'n8n-workflow'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import * as IfV2 from '../../V2/IfV2.node'; jest.mock('lodash/set', () => jest.fn()); @@ -17,7 +16,9 @@ jest.mock('lodash/set', () => jest.fn()); describe('Test IF v2 Node Tests', () => { afterEach(() => jest.resetAllMocks()); - describe('Test IF v2 Node Workflow Tests', () => testWorkflows(getWorkflowFilenames(__dirname))); + describe('Test IF v2 Node Workflow Tests', () => { + new NodeTestHarness().setupTests(); + }); describe('Test IF V2 Node Unit Tests', () => { const node = new IfV2.IfV2(mock()); diff --git a/packages/nodes-base/nodes/ItemLists/test/node/ItemLists.test.ts b/packages/nodes-base/nodes/ItemLists/test/node/ItemLists.test.ts index 467b52d55c..e86446878f 100644 --- a/packages/nodes-base/nodes/ItemLists/test/node/ItemLists.test.ts +++ b/packages/nodes-base/nodes/ItemLists/test/node/ItemLists.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test ItemLists Node', () => testWorkflows(workflows)); +describe('Test ItemLists Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Jira/test/GenericFunctions.test.ts b/packages/nodes-base/nodes/Jira/__test__/GenericFunctions.test.ts similarity index 100% rename from packages/nodes-base/nodes/Jira/test/GenericFunctions.test.ts rename to packages/nodes-base/nodes/Jira/__test__/GenericFunctions.test.ts diff --git a/packages/nodes-base/nodes/Jira/JiraTrigger.node.test.ts b/packages/nodes-base/nodes/Jira/__test__/JiraTrigger.node.test.ts similarity index 99% rename from packages/nodes-base/nodes/Jira/JiraTrigger.node.test.ts rename to packages/nodes-base/nodes/Jira/__test__/JiraTrigger.node.test.ts index c1a9868672..0e259a89c1 100644 --- a/packages/nodes-base/nodes/Jira/JiraTrigger.node.test.ts +++ b/packages/nodes-base/nodes/Jira/__test__/JiraTrigger.node.test.ts @@ -8,7 +8,7 @@ import type { import { testWebhookTriggerNode } from '@test/nodes/TriggerHelpers'; -import { JiraTrigger } from './JiraTrigger.node'; +import { JiraTrigger } from '../JiraTrigger.node'; describe('JiraTrigger', () => { describe('Webhook lifecycle', () => { diff --git a/packages/nodes-base/nodes/Jira/test/node.methods.test.ts b/packages/nodes-base/nodes/Jira/__test__/node.methods.test.ts similarity index 100% rename from packages/nodes-base/nodes/Jira/test/node.methods.test.ts rename to packages/nodes-base/nodes/Jira/__test__/node.methods.test.ts diff --git a/packages/nodes-base/nodes/Jwt/test/Jwt.node.test.ts b/packages/nodes-base/nodes/Jwt/test/Jwt.node.test.ts index 6e062c1a2c..f3cdd5f3ab 100644 --- a/packages/nodes-base/nodes/Jwt/test/Jwt.node.test.ts +++ b/packages/nodes-base/nodes/Jwt/test/Jwt.node.test.ts @@ -1,4 +1,4 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; const credentials = { jwtAuth: { @@ -8,6 +8,6 @@ const credentials = { }, }; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Jwt Node', () => testWorkflows(workflows, credentials)); +describe('Test Jwt Node', () => { + new NodeTestHarness().setupTests({ credentials }); +}); diff --git a/packages/nodes-base/nodes/Kafka/Kafka.node.test.ts b/packages/nodes-base/nodes/Kafka/test/Kafka.node.test.ts similarity index 92% rename from packages/nodes-base/nodes/Kafka/Kafka.node.test.ts rename to packages/nodes-base/nodes/Kafka/test/Kafka.node.test.ts index 27d20d750a..2d1bf41547 100644 --- a/packages/nodes-base/nodes/Kafka/Kafka.node.test.ts +++ b/packages/nodes-base/nodes/Kafka/test/Kafka.node.test.ts @@ -1,10 +1,8 @@ import { SchemaRegistry } from '@kafkajs/confluent-schema-registry'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { mock } from 'jest-mock-extended'; import type { Producer } from 'kafkajs'; import { Kafka as apacheKafka } from 'kafkajs'; -import path from 'path'; - -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; jest.mock('kafkajs'); jest.mock('@kafkajs/confluent-schema-registry'); @@ -43,8 +41,7 @@ describe('Kafka Node', () => { (SchemaRegistry as jest.Mock).mockReturnValue(mockRegistry); }); - const workflows = getWorkflowFilenames(path.join(__dirname, 'test')); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); test('should publish the correct kafka messages', async () => { expect(mockProducerSend).toHaveBeenCalledTimes(2); diff --git a/packages/nodes-base/nodes/Kafka/KafkaTrigger.node.test.ts b/packages/nodes-base/nodes/Kafka/test/KafkaTrigger.node.test.ts similarity index 99% rename from packages/nodes-base/nodes/Kafka/KafkaTrigger.node.test.ts rename to packages/nodes-base/nodes/Kafka/test/KafkaTrigger.node.test.ts index c543b0fb5b..dbce69f021 100644 --- a/packages/nodes-base/nodes/Kafka/KafkaTrigger.node.test.ts +++ b/packages/nodes-base/nodes/Kafka/test/KafkaTrigger.node.test.ts @@ -14,7 +14,7 @@ import { NodeOperationError } from 'n8n-workflow'; import { testTriggerNode } from '@test/nodes/TriggerHelpers'; -import { KafkaTrigger } from './KafkaTrigger.node'; +import { KafkaTrigger } from '../KafkaTrigger.node'; jest.mock('kafkajs'); jest.mock('@kafkajs/confluent-schema-registry'); diff --git a/packages/nodes-base/nodes/MailerLite/tests/v1/MailerLite.v1.workflow.test.ts b/packages/nodes-base/nodes/MailerLite/tests/v1/MailerLite.v1.workflow.test.ts index 419eec40ea..31b1231fbb 100644 --- a/packages/nodes-base/nodes/MailerLite/tests/v1/MailerLite.v1.workflow.test.ts +++ b/packages/nodes-base/nodes/MailerLite/tests/v1/MailerLite.v1.workflow.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { getCreateResponseClassic, getSubscriberResponseClassic, @@ -20,7 +19,6 @@ describe('MailerLite', () => { mock.put('/subscribers/demo@mailerlite.com').reply(200, getUpdateSubscriberResponseClassic); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); }); diff --git a/packages/nodes-base/nodes/MailerLite/tests/v2/MailerLite.v2.workflow.test.ts b/packages/nodes-base/nodes/MailerLite/tests/v2/MailerLite.v2.workflow.test.ts index 2ec639b55f..9221ce9e78 100644 --- a/packages/nodes-base/nodes/MailerLite/tests/v2/MailerLite.v2.workflow.test.ts +++ b/packages/nodes-base/nodes/MailerLite/tests/v2/MailerLite.v2.workflow.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { getCreateResponseV2, getSubscriberResponseV2, @@ -23,7 +22,6 @@ describe('MailerLite', () => { mock.put('/subscribers/user@n8n.io').reply(200, getUpdateSubscriberResponseV2); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); }); diff --git a/packages/nodes-base/nodes/Markdown/test/node/Markdown.test.ts b/packages/nodes-base/nodes/Markdown/test/node/Markdown.test.ts index dc8b584dca..06569d2262 100644 --- a/packages/nodes-base/nodes/Markdown/test/node/Markdown.test.ts +++ b/packages/nodes-base/nodes/Markdown/test/node/Markdown.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Markdown Node', () => testWorkflows(workflows)); +describe('Test Markdown Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Merge/test/node/Merge.test.ts b/packages/nodes-base/nodes/Merge/test/node/Merge.test.ts index 5edb910df9..27c26f5aa4 100644 --- a/packages/nodes-base/nodes/Merge/test/node/Merge.test.ts +++ b/packages/nodes-base/nodes/Merge/test/node/Merge.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Merge Node', () => testWorkflows(workflows)); +describe('Test Merge Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/create.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/create.test.ts index 37765758a2..d902b5ee0f 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/create.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Create Container', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('create.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -75,5 +70,8 @@ describe('Azure Cosmos DB - Create Container', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/delete.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/delete.test.ts index daaa6faadb..aebe2f1064 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/delete.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/delete.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Delete Container', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('delete.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -19,5 +14,8 @@ describe('Azure Cosmos DB - Delete Container', () => { .reply(204, {}); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['delete.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/get.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/get.test.ts index fb74c3ef9d..b4df446c6e 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/get.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Get Container', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('get.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -57,5 +52,8 @@ describe('Azure Cosmos DB - Get Container', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/getAll.test.ts index 4218e31f48..3e14653fe6 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/container/getAll.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Get All Containers', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('getAll.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -159,5 +154,8 @@ describe('Azure Cosmos DB - Get All Containers', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/create.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/create.test.ts index 0d9f66fa98..06650a23b2 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/create.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Create Item', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('create.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -57,5 +52,8 @@ describe('Azure Cosmos DB - Create Item', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/delete.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/delete.test.ts index d557f3b485..cbddcbb17d 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/delete.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/delete.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Delete Item', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('delete.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -50,5 +45,8 @@ describe('Azure Cosmos DB - Delete Item', () => { .reply(204, ''); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['delete.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/get.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/get.test.ts index ac86066888..880a8de6db 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/get.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Get Item', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('get.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -58,5 +53,8 @@ describe('Azure Cosmos DB - Get Item', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/getAll.test.ts index 6f2bc49394..5d2c2712de 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/getAll.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Get All Items', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('getAll.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -69,5 +64,8 @@ describe('Azure Cosmos DB - Get All Items', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/query.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/query.test.ts index 43ba02653c..bb860beec9 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/query.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/query.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Query Items', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('query.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -34,5 +29,8 @@ describe('Azure Cosmos DB - Query Items', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['query.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/update.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/update.test.ts index 860f7345b1..44571c529b 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/update.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/item/update.test.ts @@ -1,14 +1,9 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { credentials } from '../credentials'; describe('Azure Cosmos DB - Update Item', () => { - const workflows = getWorkflowFilenames(__dirname).filter((filename) => - filename.includes('update.workflow.json'), - ); - beforeEach(() => { const { baseUrl } = credentials.microsoftAzureCosmosDbSharedKeyApi; @@ -62,5 +57,8 @@ describe('Azure Cosmos DB - Update Item', () => { }); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Entra/test/GroupDescription.test.ts b/packages/nodes-base/nodes/Microsoft/Entra/test/GroupDescription.test.ts index c82ff3011c..01f1e876ca 100644 --- a/packages/nodes-base/nodes/Microsoft/Entra/test/GroupDescription.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Entra/test/GroupDescription.test.ts @@ -1,12 +1,11 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks'; describe('Microsoft Entra Node', () => { const baseUrl = 'https://graph.microsoft.com/v1.0'; + const testHarness = new NodeTestHarness(); describe('Group description', () => { const tests: WorkflowTestData[] = [ @@ -73,7 +72,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.createGroup], }, @@ -165,7 +163,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.deleteGroup], }, @@ -236,7 +233,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.getGroup], }, @@ -353,7 +349,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.getGroupWithProperties], }, @@ -421,7 +416,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [new Array(102).fill(microsoftEntraNodeResponse.getGroup[0])], }, @@ -503,7 +497,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [new Array(10).fill(microsoftEntraNodeResponse.getGroup[0])], }, @@ -612,7 +605,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [ new Array(102).fill(microsoftEntraNodeResponse.getGroupWithProperties[0]), @@ -711,7 +703,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.updateGroup], }, @@ -751,14 +742,8 @@ describe('Microsoft Entra Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.status).toEqual('success'); - }); + for (const testData of tests) { + testHarness.setupTest(testData); + } }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Entra/test/MicrosoftEntra.node.test.ts b/packages/nodes-base/nodes/Microsoft/Entra/test/MicrosoftEntra.node.test.ts index 233e1a1ded..3a07d934d6 100644 --- a/packages/nodes-base/nodes/Microsoft/Entra/test/MicrosoftEntra.node.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Entra/test/MicrosoftEntra.node.test.ts @@ -1,13 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { ILoadOptionsFunctions, WorkflowTestData } from 'n8n-workflow'; import { NodeConnectionTypes } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks'; import { MicrosoftEntra } from '../MicrosoftEntra.node'; describe('Microsoft Entra Node', () => { + const testHarness = new NodeTestHarness(); const baseUrl = 'https://graph.microsoft.com/v1.0'; describe('Credentials', () => { @@ -76,7 +75,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.getGroup], }, @@ -94,18 +92,12 @@ describe('Microsoft Entra Node', () => { }, ], }, - credentials, }, ]; - test.each(tests)('$description', async (testData) => { - const { result } = await executeWorkflow(testData); - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.status).toEqual('success'); - }); + for (const testData of tests) { + testHarness.setupTest(testData, { credentials }); + } }); describe('Load options', () => { diff --git a/packages/nodes-base/nodes/Microsoft/Entra/test/UserDescription.test.ts b/packages/nodes-base/nodes/Microsoft/Entra/test/UserDescription.test.ts index 27fcca5101..c235b06bb5 100644 --- a/packages/nodes-base/nodes/Microsoft/Entra/test/UserDescription.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Entra/test/UserDescription.test.ts @@ -1,11 +1,10 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - import { microsoftEntraApiResponse, microsoftEntraNodeResponse } from './mocks'; describe('Microsoft Entra Node', () => { + const testHarness = new NodeTestHarness(); const baseUrl = 'https://graph.microsoft.com/v1.0'; describe('User description', () => { @@ -68,7 +67,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.addUserToGroup], }, @@ -183,7 +181,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.createUser], }, @@ -320,7 +317,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.deleteUser], }, @@ -391,7 +387,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.getUser], }, @@ -539,7 +534,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [ [ @@ -620,7 +614,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [new Array(102).fill(microsoftEntraNodeResponse.getUser[0])], }, @@ -702,7 +695,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [new Array(10).fill(microsoftEntraNodeResponse.getUser[0])], }, @@ -842,7 +834,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [ new Array(102).fill({ @@ -944,7 +935,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.removeUserFromGroup], }, @@ -1062,7 +1052,6 @@ describe('Microsoft Entra Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { 'Micosoft Entra ID': [microsoftEntraNodeResponse.updateUser], }, @@ -1137,14 +1126,8 @@ describe('Microsoft Entra Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.status).toEqual('success'); - }); + for (const testData of tests) { + testHarness.setupTest(testData); + } }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/addTable.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/addTable.test.ts index 794d3f95c3..4f1442eb45 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/addTable.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/addTable.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => addTable', () => { @@ -24,6 +23,8 @@ describe('Test MicrosoftExcelV2, table => addTable', () => { showTotals: false, }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/addTable.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['addTable.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/append.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/append.test.ts index 1c734a0d82..ec5abfc1e7 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/append.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/append.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => append', () => { @@ -25,6 +24,8 @@ describe('Test MicrosoftExcelV2, table => append', () => { .post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/closeSession') .reply(200); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/append.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['append.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/convertToRange.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/convertToRange.test.ts index 8cef6af557..904808ff48 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/convertToRange.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/convertToRange.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => convertToRange', () => { @@ -20,6 +19,8 @@ describe('Test MicrosoftExcelV2, table => convertToRange', () => { ], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/convertToRange.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['convertToRange.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/deleteTable.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/deleteTable.test.ts index dc11e8aafa..0b84a82c4b 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/deleteTable.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/deleteTable.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => deleteTable', () => { @@ -11,6 +10,8 @@ describe('Test MicrosoftExcelV2, table => deleteTable', () => { ) .reply(200); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/deleteTable.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['deleteTable.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getColumns.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getColumns.test.ts index c5faff5f8c..b765496fa8 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getColumns.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getColumns.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => getColumns', () => { @@ -22,6 +21,8 @@ describe('Test MicrosoftExcelV2, table => getColumns', () => { ) .reply(200, { value: [] }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/getColumns.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getColumns.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getRows.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getRows.test.ts index 022579dc6d..39f7e61e46 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getRows.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/getRows.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => getRows', () => { @@ -31,6 +30,8 @@ describe('Test MicrosoftExcelV2, table => getRows', () => { ) .reply(200, { value: [] }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/getRows.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getRows.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/lookup.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/lookup.test.ts index c2db36e45b..608cf874eb 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/lookup.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/table/lookup.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, table => lookup', () => { @@ -39,6 +38,8 @@ describe('Test MicrosoftExcelV2, table => lookup', () => { ) .reply(200, { value: [] }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/table/lookup.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['lookup.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.test.ts index 81bc1a7d46..99cdb5fa17 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, workbook => addWorksheet', () => { @@ -23,6 +22,8 @@ describe('Test MicrosoftExcelV2, workbook => addWorksheet', () => { .post('/drive/items/01FUWX3BQ4ATCOZNR265GLA6IJEZDQUE4I/workbook/closeSession') .reply(200); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/addWorksheet.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['addWorksheet.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.test.ts index 6006163218..9928c811df 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, workbook => deleteWorkbook', () => { @@ -9,6 +8,8 @@ describe('Test MicrosoftExcelV2, workbook => deleteWorkbook', () => { .delete('/drive/items/01FUWX3BXJLISGF2CFWBGYPHXFCXPXOJUK') .reply(200); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/deleteWorkbook.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['deleteWorkbook.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/getAll.test.ts index 0273a71c02..d1e2182e4d 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/workbook/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, workbook => getAll', () => { @@ -20,6 +19,8 @@ describe('Test MicrosoftExcelV2, workbook => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/workbook/getAll.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/append.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/append.test.ts index 4f6eea86ea..cce3889e95 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/append.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/append.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => append', () => { @@ -39,6 +38,8 @@ describe('Test MicrosoftExcelV2, worksheet => append', () => { ) .reply(200, { values: [[4, 'Don', 37, 'data 44']] }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/append.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['append.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/clear.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/clear.test.ts index 1c3c2c2bd7..556f2671bb 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/clear.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/clear.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => clear', () => { @@ -14,6 +13,8 @@ describe('Test MicrosoftExcelV2, worksheet => clear', () => { values: [{ json: { success: true } }], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/clear.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['clear.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.test.ts index 61ecdad2ac..a46ad8ad39 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => deleteWorksheet', () => { @@ -13,6 +12,8 @@ describe('Test MicrosoftExcelV2, worksheet => deleteWorksheet', () => { values: [{ json: { success: true } }], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/deleteWorksheet.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['deleteWorksheet.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.test.ts index 3a7d979c07..e49f276b8f 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => getAll', () => { @@ -26,6 +25,8 @@ describe('Test MicrosoftExcelV2, worksheet => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/getAll.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.test.ts index db0ab30827..5262842adb 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => readRows', () => { @@ -28,6 +27,8 @@ describe('Test MicrosoftExcelV2, worksheet => readRows', () => { ], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/readRows.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['readRows.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/update.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/update.test.ts index 7475c1283b..98a0034864 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/update.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => update', () => { @@ -53,6 +52,8 @@ describe('Test MicrosoftExcelV2, worksheet => update', () => { ], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/update.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.test.ts b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.test.ts index 3a78d999da..ea54558971 100644 --- a/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftExcelV2, worksheet => upsert', () => { @@ -55,6 +54,8 @@ describe('Test MicrosoftExcelV2, worksheet => upsert', () => { ], }); - const workflows = ['nodes/Microsoft/Excel/test/v2/node/worksheet/upsert.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['upsert.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/create.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/create.test.ts index 6005ad57dd..7bbfc937f2 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, calendar => create', () => { nock('https://graph.microsoft.com/v1.0/me') .post( @@ -30,6 +29,7 @@ describe('Test MicrosoftOutlookV2, calendar => create', () => { }, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/delete.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/delete.test.ts index f795dba338..b9a7287ba3 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/delete.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/delete.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, calendar => delete', () => { nock('https://graph.microsoft.com/v1.0/me') .delete( @@ -9,6 +8,7 @@ describe('Test MicrosoftOutlookV2, calendar => delete', () => { ) .reply(200); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/delete.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['delete.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/get.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/get.test.ts index 627cf72466..5286a8ea7c 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, calendar => get', () => { nock('https://graph.microsoft.com/v1.0/me') .get( @@ -29,6 +28,7 @@ describe('Test MicrosoftOutlookV2, calendar => get', () => { }, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.test.ts index 115530a286..20609b8e75 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, calendar => getAll', () => { nock('https://graph.microsoft.com/v1.0/me') .get('/calendars?%24filter=canEdit%20eq%20true&%24top=2') @@ -48,6 +47,7 @@ describe('Test MicrosoftOutlookV2, calendar => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/update.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/update.test.ts index f71cf076c7..d5e27c240a 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/update.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/calendar/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, calendar => update', () => { nock('https://graph.microsoft.com/v1.0/me') .patch( @@ -30,6 +29,7 @@ describe('Test MicrosoftOutlookV2, calendar => update', () => { }, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/calendar/update.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/create.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/create.test.ts index 348efbcb4f..9ed8320fe8 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, contact => create', () => { nock('https://graph.microsoft.com/v1.0/me') .post('/contacts', { @@ -60,6 +59,7 @@ describe('Test MicrosoftOutlookV2, contact => create', () => { otherAddress: {}, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/contact/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/update.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/update.test.ts index 8d5096b5c7..0bce0e1e4d 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/update.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/contact/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, contact => update', () => { nock('https://graph.microsoft.com/v1.0/me') .patch( @@ -70,6 +69,7 @@ describe('Test MicrosoftOutlookV2, contact => update', () => { otherAddress: {}, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/contact/update.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/create.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/create.test.ts index ab7e5a35ca..45e56eddda 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, draft => create', () => { nock('https://graph.microsoft.com/v1.0/me') .post('/messages', { @@ -95,6 +94,7 @@ describe('Test MicrosoftOutlookV2, draft => create', () => { }, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/draft/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/send.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/send.test.ts index 67d2e10b97..05766cd773 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/send.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/draft/send.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, draft => send', () => { nock('https://graph.microsoft.com/v1.0/me') .post( @@ -14,6 +13,7 @@ describe('Test MicrosoftOutlookV2, draft => send', () => { ) .reply(200); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/draft/send.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['send.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/event/create.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/event/create.test.ts index 1f880cec75..5aad7d35d7 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/event/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/event/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, contact => event', () => { nock('https://graph.microsoft.com/v1.0/me') .post( @@ -107,6 +106,7 @@ describe('Test MicrosoftOutlookV2, contact => event', () => { }, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/event/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folder/create.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folder/create.test.ts index 0eeeb2358b..f7afbe5bac 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folder/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folder/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, contact => folder', () => { nock('https://graph.microsoft.com') .post( @@ -22,6 +21,7 @@ describe('Test MicrosoftOutlookV2, contact => folder', () => { isHidden: false, }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/folder/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.test.ts index 3cd2be5f9e..9168d53254 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, folderMessage => getAll', () => { nock('https://graph.microsoft.com/v1.0/me') .get( @@ -18,6 +17,7 @@ describe('Test MicrosoftOutlookV2, folderMessage => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/folderMessage/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/move.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/move.test.ts index f65ee8a5de..de598a504b 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/move.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/move.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, message => move', () => { nock('https://graph.microsoft.com/v1.0/me') .post( @@ -13,6 +12,7 @@ describe('Test MicrosoftOutlookV2, message => move', () => { ) .reply(200); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/move.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['move.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/reply.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/reply.test.ts index 3217b99adf..feeb5136ca 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/reply.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/reply.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, message => reply', () => { nock('https://graph.microsoft.com/v1.0/me') .post( @@ -80,6 +79,7 @@ describe('Test MicrosoftOutlookV2, message => reply', () => { ) .reply(200); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/reply.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['reply.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/send.test.ts b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/send.test.ts index c6037bf244..4eb1b70087 100644 --- a/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/send.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Outlook/test/v2/node/message/send.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test MicrosoftOutlookV2, message => send', () => { nock('https://graph.microsoft.com') .post('/v1.0/me/sendMail', { @@ -15,6 +14,7 @@ describe('Test MicrosoftOutlookV2, message => send', () => { }) .reply(200, {}); - const workflows = ['nodes/Microsoft/Outlook/test/v2/node/message/send.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['send.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_create.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_create.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_create.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_create.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_delete.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_delete.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_delete.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_delete.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_get.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_get.workflow.json similarity index 97% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_get.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_get.workflow.json index 54b2800566..59c77279d9 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_get.workflow.json +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_get.workflow.json @@ -46,6 +46,7 @@ { "binary": { "data": { + "data": "ewoiZGF0YSI6ewoibXlfZmllbGRfMSI6InZhbHVlIiwKIm15X2ZpZWxkXzIiOjEKfQp9", "fileExtension": "json", "fileName": "file.json", "fileSize": "51 B", diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_getAll.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_getAll.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_getAll.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_getAll.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_getAllLimitOptions.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_getAllLimitOptions.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/blob_getAllLimitOptions.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/blob/blob_getAllLimitOptions.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/create.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/create.test.ts index 5bce0fbfad..8026cd6a94 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/create.test.ts @@ -1,64 +1,61 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_create.workflow.json']; - const workflowTests = workflowToTests(workflows); + const { baseUrl } = credentials.azureStorageOAuth2Api; - describe('should create blob', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'put', - path: '/mycontainer/myblob', - statusCode: 201, - requestHeaders: { - 'x-ms-access-tier': 'Hot', - 'x-ms-blob-type': 'BlockBlob', - 'x-ms-blob-cache-control': 'no-cache', - 'x-ms-content-crc64': '3EDB64E77CB16A4C', - 'x-ms-blob-content-encoding': 'utf8', - 'x-ms-blob-content-language': 'en-US', - 'x-ms-blob-content-md5': 'b97f46db5f3be7709d942eefe30e5b45', - 'x-ms-blob-content-type': 'application/json', - 'x-ms-encryption-context': 'context', - 'x-ms-encryption-scope': 'encryptionScope', - 'x-ms-expiry-option': 'Absolute', - 'x-ms-blob-content-disposition': 'attachment; filename="file.json"', - 'x-ms-immutability-policy-until-date': 'Wed, 01 Jan 2025 00:00:00 -0500', - 'x-ms-immutability-policy-mode': 'unlocked', - 'x-ms-lease-id': 'leaseId123', - 'x-ms-legal-hold': 'true', - 'x-ms-meta-key1': 'value1', - }, - responseBody: '', - responseHeaders: { - server: 'Azurite-Blob/3.33.0', - etag: '"0x22769D26D3F3740"', - 'last-modified': 'Thu, 23 Jan 2025 17:53:23 GMT', - 'content-md5': 'aWQGHD8kGQd5ZtEN/S1/aw==', - 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', - 'x-ms-version': '2025-01-05', - date: 'Thu, 23 Jan 2025 17:53:23 GMT', - 'x-ms-request-server-encrypted': 'true', - 'keep-alive': 'timeout=5', - 'content-length': '0', - 'x-ms-version-id': 'Thu, 23 Jan 2025 17:53:23 GMT', - 'access-control-allow-credentials': 'access-control-allow-credentials', - 'access-control-allow-origin': 'access-control-allow-origin', - 'access-control-expose-headers': 'access-control-expose-headers', - 'x-ms-content-crc64': 'x-ms-content-crc64', - 'x-ms-encryption-key-sha256': 'x-ms-encryption-key-sha256', - 'x-ms-encryption-scope': 'x-ms-encryption-scope', - }, + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['blob_create.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'put', + path: '/mycontainer/myblob', + statusCode: 201, + requestHeaders: { + 'x-ms-access-tier': 'Hot', + 'x-ms-blob-type': 'BlockBlob', + 'x-ms-blob-cache-control': 'no-cache', + 'x-ms-content-crc64': '3EDB64E77CB16A4C', + 'x-ms-blob-content-encoding': 'utf8', + 'x-ms-blob-content-language': 'en-US', + 'x-ms-blob-content-md5': 'b97f46db5f3be7709d942eefe30e5b45', + 'x-ms-blob-content-type': 'application/json', + 'x-ms-encryption-context': 'context', + 'x-ms-encryption-scope': 'encryptionScope', + 'x-ms-expiry-option': 'Absolute', + 'x-ms-blob-content-disposition': 'attachment; filename="file.json"', + 'x-ms-immutability-policy-until-date': 'Wed, 01 Jan 2025 00:00:00 -0500', + 'x-ms-immutability-policy-mode': 'unlocked', + 'x-ms-lease-id': 'leaseId123', + 'x-ms-legal-hold': 'true', + 'x-ms-meta-key1': 'value1', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + responseBody: '', + responseHeaders: { + server: 'Azurite-Blob/3.33.0', + etag: '"0x22769D26D3F3740"', + 'last-modified': 'Thu, 23 Jan 2025 17:53:23 GMT', + 'content-md5': 'aWQGHD8kGQd5ZtEN/S1/aw==', + 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', + 'x-ms-version': '2025-01-05', + date: 'Thu, 23 Jan 2025 17:53:23 GMT', + 'x-ms-request-server-encrypted': 'true', + 'keep-alive': 'timeout=5', + 'content-length': '0', + 'x-ms-version-id': 'Thu, 23 Jan 2025 17:53:23 GMT', + 'access-control-allow-credentials': 'access-control-allow-credentials', + 'access-control-allow-origin': 'access-control-allow-origin', + 'access-control-expose-headers': 'access-control-expose-headers', + 'x-ms-content-crc64': 'x-ms-content-crc64', + 'x-ms-encryption-key-sha256': 'x-ms-encryption-key-sha256', + 'x-ms-encryption-scope': 'x-ms-encryption-scope', + }, + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/delete.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/delete.test.ts index 6d5560a66a..dd36553357 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/delete.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/delete.test.ts @@ -1,33 +1,30 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_delete.workflow.json']; - const workflowTests = workflowToTests(workflows); + const { baseUrl } = credentials.azureStorageOAuth2Api; - describe('should delete blob', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'delete', - path: '/mycontainer/myblob', - statusCode: 202, - responseBody: '', - responseHeaders: { - 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', - 'x-ms-version': '2025-01-05', - date: 'Thu, 23 Jan 2025 17:53:23 GMT', - 'x-ms-delete-type-permanent': 'true', - 'x-ms-client-request-id': 'x-ms-client-request-id', - }, + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['blob_delete.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'delete', + path: '/mycontainer/myblob', + statusCode: 202, + responseBody: '', + responseHeaders: { + 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', + 'x-ms-version': '2025-01-05', + date: 'Thu, 23 Jan 2025 17:53:23 GMT', + 'x-ms-delete-type-permanent': 'true', + 'x-ms-client-request-id': 'x-ms-client-request-id', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/get.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/get.test.ts index b6a353b00c..b0eb1b56e1 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/get.test.ts @@ -1,85 +1,82 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_get.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should get blob', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/mycontainer/myblob', - statusCode: 200, - responseBody: { - type: 'Buffer', - data: [ - 123, 10, 34, 100, 97, 116, 97, 34, 58, 123, 10, 34, 109, 121, 95, 102, 105, 101, - 108, 100, 95, 49, 34, 58, 34, 118, 97, 108, 117, 101, 34, 44, 10, 34, 109, 121, 95, - 102, 105, 101, 108, 100, 95, 50, 34, 58, 49, 10, 125, 10, 125, - ], - }, - responseHeaders: { - 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', - 'x-ms-version': '2025-01-05', - date: 'Thu, 23 Jan 2025 17:53:23 GMT', - 'x-ms-client-request-id': 'x-ms-client-request-id', - 'last-modified': 'last-modified', - 'x-ms-creation-time': 'x-ms-creation-time', - 'x-ms-tag-count': 'x-ms-tag-count', - 'content-type': 'application/json', - 'content-range': 'content-range', - etag: '"0x22769D26D3F3740"', - 'content-md5': 'content-md5', - 'x-ms-content-crc64': 'x-ms-content-crc64', - 'content-encoding': 'content-encoding', - 'content-language': 'content-language', - 'cache-control': 'cache-control', - 'content-disposition': 'attachment; filename="file.json"', - 'x-ms-blob-sequence-number': 'x-ms-blob-sequence-number', - 'x-ms-blob-type': 'x-ms-blob-type', - 'x-ms-copy-completion-time': 'x-ms-copy-completion-time', - 'x-ms-copy-status-description': 'x-ms-copy-status-description', - 'x-ms-copy-id': 'x-ms-copy-id', - 'x-ms-copy-progress': 'x-ms-copy-progress', - 'x-ms-copy-source': 'x-ms-copy-source', - 'x-ms-copy-status': 'x-ms-copy-status', - 'x-ms-incremental-copy': 'x-ms-incremental-copy', - 'x-ms-lease-duration': 'x-ms-lease-duration', - 'x-ms-lease-state': 'x-ms-lease-state', - 'x-ms-lease-status': 'x-ms-lease-status', - 'accept-ranges': 'accept-ranges', - 'access-control-allow-origin': 'access-control-allow-origin', - 'access-control-expose-headers': 'access-control-expose-headers', - vary: 'vary', - 'access-control-allow-credentials': 'access-control-allow-credentials', - 'x-ms-blob-committed-block-count': 'x-ms-blob-committed-block-count', - 'x-ms-server-encrypted': 'x-ms-server-encrypted', - 'x-ms-encryption-key-sha256': 'x-ms-encryption-key-sha256', - 'x-ms-encryption-context': 'x-ms-encryption-context', - 'x-ms-encryption-scope': 'x-ms-encryption-scope', - 'x-ms-blob-content-md5': 'x-ms-blob-content-md5', - 'x-ms-last-access-time': 'x-ms-last-access-time', - 'x-ms-blob-sealed': 'x-ms-blob-sealed', - 'x-ms-immutability-policy-until-date': 'x-ms-immutability-policy-until-date', - 'x-ms-immutability-policy-mode': 'x-ms-immutability-policy-mode', - 'x-ms-legal-hold': 'x-ms-legal-hold', - 'x-ms-owner': 'x-ms-owner', - 'x-ms-group': 'x-ms-group', - 'x-ms-permissions': 'x-ms-permissions', - 'x-ms-acl': 'x-ms-acl', - 'x-ms-resource-type': 'x-ms-resource-type', - 'x-ms-meta-key1': 'value1', - }, + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['blob_get.workflow.json'], + assertBinaryData: true, + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/mycontainer/myblob', + statusCode: 200, + responseBody: { + type: 'Buffer', + data: [ + 123, 10, 34, 100, 97, 116, 97, 34, 58, 123, 10, 34, 109, 121, 95, 102, 105, 101, 108, + 100, 95, 49, 34, 58, 34, 118, 97, 108, 117, 101, 34, 44, 10, 34, 109, 121, 95, 102, + 105, 101, 108, 100, 95, 50, 34, 58, 49, 10, 125, 10, 125, + ], }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + responseHeaders: { + 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', + 'x-ms-version': '2025-01-05', + date: 'Thu, 23 Jan 2025 17:53:23 GMT', + 'x-ms-client-request-id': 'x-ms-client-request-id', + 'last-modified': 'last-modified', + 'x-ms-creation-time': 'x-ms-creation-time', + 'x-ms-tag-count': 'x-ms-tag-count', + 'content-type': 'application/json', + 'content-range': 'content-range', + etag: '"0x22769D26D3F3740"', + 'content-md5': 'content-md5', + 'x-ms-content-crc64': 'x-ms-content-crc64', + 'content-encoding': 'content-encoding', + 'content-language': 'content-language', + 'cache-control': 'cache-control', + 'content-disposition': 'attachment; filename="file.json"', + 'x-ms-blob-sequence-number': 'x-ms-blob-sequence-number', + 'x-ms-blob-type': 'x-ms-blob-type', + 'x-ms-copy-completion-time': 'x-ms-copy-completion-time', + 'x-ms-copy-status-description': 'x-ms-copy-status-description', + 'x-ms-copy-id': 'x-ms-copy-id', + 'x-ms-copy-progress': 'x-ms-copy-progress', + 'x-ms-copy-source': 'x-ms-copy-source', + 'x-ms-copy-status': 'x-ms-copy-status', + 'x-ms-incremental-copy': 'x-ms-incremental-copy', + 'x-ms-lease-duration': 'x-ms-lease-duration', + 'x-ms-lease-state': 'x-ms-lease-state', + 'x-ms-lease-status': 'x-ms-lease-status', + 'accept-ranges': 'accept-ranges', + 'access-control-allow-origin': 'access-control-allow-origin', + 'access-control-expose-headers': 'access-control-expose-headers', + vary: 'vary', + 'access-control-allow-credentials': 'access-control-allow-credentials', + 'x-ms-blob-committed-block-count': 'x-ms-blob-committed-block-count', + 'x-ms-server-encrypted': 'x-ms-server-encrypted', + 'x-ms-encryption-key-sha256': 'x-ms-encryption-key-sha256', + 'x-ms-encryption-context': 'x-ms-encryption-context', + 'x-ms-encryption-scope': 'x-ms-encryption-scope', + 'x-ms-blob-content-md5': 'x-ms-blob-content-md5', + 'x-ms-last-access-time': 'x-ms-last-access-time', + 'x-ms-blob-sealed': 'x-ms-blob-sealed', + 'x-ms-immutability-policy-until-date': 'x-ms-immutability-policy-until-date', + 'x-ms-immutability-policy-mode': 'x-ms-immutability-policy-mode', + 'x-ms-legal-hold': 'x-ms-legal-hold', + 'x-ms-owner': 'x-ms-owner', + 'x-ms-group': 'x-ms-group', + 'x-ms-permissions': 'x-ms-permissions', + 'x-ms-acl': 'x-ms-acl', + 'x-ms-resource-type': 'x-ms-resource-type', + 'x-ms-meta-key1': 'value1', + }, + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAll.test.ts index da71d317e9..b8c0da4e70 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAll.test.ts @@ -1,34 +1,28 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/blob_getAll.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should get all blobs', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/mycontainer?restype=container&comp=list', - statusCode: 200, - responseBody: - '1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMTmyblob2', - }, - { - method: 'get', - path: '/mycontainer?restype=container&comp=list&marker=myblob2', - statusCode: 200, - responseBody: - '1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMT', - }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['blob_getAll.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/mycontainer?restype=container&comp=list', + statusCode: 200, + responseBody: `1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMTmyblob2`, + }, + { + method: 'get', + path: '/mycontainer?restype=container&comp=list&marker=myblob2', + statusCode: 200, + responseBody: `1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMT`, + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAllLimitOptions.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAllLimitOptions.test.ts index ec3eec67ab..12fd1e8f06 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAllLimitOptions.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/blob/getAllLimitOptions.test.ts @@ -1,29 +1,22 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = [ - 'nodes/Microsoft/Storage/test/workflows/blob_getAllLimitOptions.workflow.json', - ]; - const workflowTests = workflowToTests(workflows); - - describe('should get all blobs with limit and options', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/mycontainer?restype=container&comp=list&maxresults=1&include=copy%2Cdeleted%2Cdeletedwithversions%2Cimmutabilitypolicy%2Cmetadata%2Clegalhold%2Cversions%2Cuncommittedblobs%2Ctags%2Csnapshots%2Cpermissions&showonly=deleted%2Cfiles%2Cdirectories', - statusCode: 200, - responseBody: - '1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMTmyblob2', - }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['blob_getAllLimitOptions.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/mycontainer?restype=container&comp=list&maxresults=1&include=copy%2Cdeleted%2Cdeletedwithversions%2Cimmutabilitypolicy%2Cmetadata%2Clegalhold%2Cversions%2Cuncommittedblobs%2Ctags%2Csnapshots%2Cpermissions&showonly=deleted%2Cfiles%2Cdirectories', + statusCode: 200, + responseBody: `1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMTmyblob2`, + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_create.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/container/container_create.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_create.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/container/container_create.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_delete.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/container/container_delete.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_delete.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/container/container_delete.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_get.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/container/container_get.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_get.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/container/container_get.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_getAll.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/container/container_getAll.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_getAll.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/container/container_getAll.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_getAllLimitOptions.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/container/container_getAllLimitOptions.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/container_getAllLimitOptions.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/container/container_getAllLimitOptions.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/container/create.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/container/create.test.ts index 6b26834ed1..e77f894844 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/container/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/container/create.test.ts @@ -1,36 +1,32 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/container_create.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should create container', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'put', - path: '/mycontainer?restype=container', - statusCode: 201, - requestHeaders: { 'x-ms-blob-public-access': 'blob', 'x-ms-meta-key1': 'value1' }, - responseBody: '', - responseHeaders: { - etag: '"0x22769D26D3F3740"', - 'last-modified': 'Thu, 23 Jan 2025 17:53:23 GMT', - 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', - 'x-ms-version': '2025-01-05', - date: 'Thu, 23 Jan 2025 17:53:23 GMT', - 'x-ms-request-server-encrypted': 'true', - 'x-ms-client-request-id': 'client-request-id-123', - }, + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['container_create.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'put', + path: '/mycontainer?restype=container', + statusCode: 201, + requestHeaders: { 'x-ms-blob-public-access': 'blob', 'x-ms-meta-key1': 'value1' }, + responseBody: '', + responseHeaders: { + etag: '"0x22769D26D3F3740"', + 'last-modified': 'Thu, 23 Jan 2025 17:53:23 GMT', + 'x-ms-request-id': '75b87ee3-a7f7-468d-b7d1-e7e7b3173dab', + 'x-ms-version': '2025-01-05', + date: 'Thu, 23 Jan 2025 17:53:23 GMT', + 'x-ms-request-server-encrypted': 'true', + 'x-ms-client-request-id': 'client-request-id-123', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/container/delete.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/container/delete.test.ts index cd71ff362a..5a68fe9fd1 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/container/delete.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/container/delete.test.ts @@ -1,33 +1,29 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/container_delete.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should delete container', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'delete', - path: '/mycontainer?restype=container', - statusCode: 202, - responseBody: '', - responseHeaders: { - 'content-length': '0', - server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', - 'x-ms-request-id': 'ca3a8907-601e-0050-1929-723410000000', - 'x-ms-version': '2020-10-02', - date: 'Wed, 29 Jan 2025 08:38:21 GMT', - }, + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['container_delete.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'delete', + path: '/mycontainer?restype=container', + statusCode: 202, + responseBody: '', + responseHeaders: { + 'content-length': '0', + server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', + 'x-ms-request-id': 'ca3a8907-601e-0050-1929-723410000000', + 'x-ms-version': '2020-10-02', + date: 'Wed, 29 Jan 2025 08:38:21 GMT', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/container/get.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/container/get.test.ts index b4ceb451fa..e8f8ef2e32 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/container/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/container/get.test.ts @@ -1,42 +1,38 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/container_get.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should get container', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/mycontainer?restype=container', - statusCode: 200, - responseBody: '', - responseHeaders: { - 'content-length': '0', - 'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT', - etag: '"0x8DD3FBA74CF3620"', - server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', - 'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000', - 'x-ms-version': '2020-10-02', - 'x-ms-lease-status': 'unlocked', - 'x-ms-lease-state': 'available', - 'x-ms-has-immutability-policy': 'false', - 'x-ms-has-legal-hold': 'false', - date: 'Wed, 29 Jan 2025 08:43:08 GMT', - 'x-ms-meta-key1': 'field1', - 'x-ms-blob-public-access': 'blob', - 'x-ms-lease-duration': 'infinite', - }, + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['container_get.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/mycontainer?restype=container', + statusCode: 200, + responseBody: '', + responseHeaders: { + 'content-length': '0', + 'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT', + etag: '"0x8DD3FBA74CF3620"', + server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', + 'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000', + 'x-ms-version': '2020-10-02', + 'x-ms-lease-status': 'unlocked', + 'x-ms-lease-state': 'available', + 'x-ms-has-immutability-policy': 'false', + 'x-ms-has-legal-hold': 'false', + date: 'Wed, 29 Jan 2025 08:43:08 GMT', + 'x-ms-meta-key1': 'field1', + 'x-ms-blob-public-access': 'blob', + 'x-ms-lease-duration': 'infinite', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAll.test.ts index cf7f8e54a3..67939b8344 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAll.test.ts @@ -1,34 +1,28 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/container_getAll.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should get all containers', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/?comp=list', - statusCode: 200, - responseBody: - 'mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1mycontainer2', - }, - { - method: 'get', - path: '/?comp=list&marker=mycontainer2', - statusCode: 200, - responseBody: - 'mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1', - }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['container_getAll.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/?comp=list', + statusCode: 200, + responseBody: `mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1mycontainer2`, + }, + { + method: 'get', + path: '/?comp=list&marker=mycontainer2', + statusCode: 200, + responseBody: `mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1`, + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAllLimitOptions.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAllLimitOptions.test.ts index fe863e44e2..d2b8ec08f2 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAllLimitOptions.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/container/getAllLimitOptions.test.ts @@ -1,29 +1,22 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = [ - 'nodes/Microsoft/Storage/test/workflows/container_getAllLimitOptions.workflow.json', - ]; - const workflowTests = workflowToTests(workflows); - - describe('should get all containers with limit and options', () => { - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/?comp=list&maxresults=1&include=metadata%2Cdeleted%2Csystem&prefix=mycontainer', - statusCode: 200, - responseBody: - 'mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1mycontainer2', - }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['container_getAllLimitOptions.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/?comp=list&maxresults=1&include=metadata%2Cdeleted%2Csystem&prefix=mycontainer', + statusCode: 200, + responseBody: `mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1mycontainer2`, + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/credentials_oauth2.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/credentials_oauth2.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/credentials_oauth2.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/credentials/credentials_oauth2.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/workflows/credentials_sharedKey.workflow.json b/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/credentials_sharedKey.workflow.json similarity index 100% rename from packages/nodes-base/nodes/Microsoft/Storage/test/workflows/credentials_sharedKey.workflow.json rename to packages/nodes-base/nodes/Microsoft/Storage/test/credentials/credentials_sharedKey.workflow.json diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/oauth2.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/oauth2.test.ts index e1eb9a4706..a429e543e5 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/oauth2.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/oauth2.test.ts @@ -1,44 +1,38 @@ -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { - const workflows = ['nodes/Microsoft/Storage/test/workflows/credentials_oauth2.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should use correct oauth2 credentials', () => { - beforeEach(() => jest.restoreAllMocks()); - - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl: 'https://myaccount.blob.core.windows.net', - mocks: [ - { - method: 'get', - path: '/mycontainer?restype=container', - statusCode: 200, - responseBody: '', - responseHeaders: { - 'content-length': '0', - 'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT', - etag: '"0x8DD3FBA74CF3620"', - server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', - 'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000', - 'x-ms-version': '2020-10-02', - 'x-ms-lease-status': 'unlocked', - 'x-ms-lease-state': 'available', - 'x-ms-has-immutability-policy': 'false', - 'x-ms-has-legal-hold': 'false', - date: 'Wed, 29 Jan 2025 08:43:08 GMT', - 'x-ms-meta-key1': 'field1', - 'x-ms-blob-public-access': 'blob', - 'x-ms-lease-duration': 'infinite', - }, + const { baseUrl } = credentials.azureStorageOAuth2Api; + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['credentials_oauth2.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/mycontainer?restype=container', + statusCode: 200, + responseBody: '', + responseHeaders: { + 'content-length': '0', + 'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT', + etag: '"0x8DD3FBA74CF3620"', + server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', + 'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000', + 'x-ms-version': '2020-10-02', + 'x-ms-lease-status': 'unlocked', + 'x-ms-lease-state': 'available', + 'x-ms-has-immutability-policy': 'false', + 'x-ms-has-legal-hold': 'false', + date: 'Wed, 29 Jan 2025 08:43:08 GMT', + 'x-ms-meta-key1': 'field1', + 'x-ms-blob-public-access': 'blob', + 'x-ms-lease-duration': 'infinite', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + }, + ], + }, }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/sharedKey.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/sharedKey.test.ts index 8bb0a165b5..15471eeaa7 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/sharedKey.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/credentials/sharedKey.test.ts @@ -1,49 +1,42 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { ICredentialDataDecryptedObject, IHttpRequestOptions } from 'n8n-workflow'; import { AzureStorageSharedKeyApi } from '@credentials/AzureStorageSharedKeyApi.credentials'; -import { equalityTest, workflowToTests } from '@test/nodes/Helpers'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { const { account, baseUrl, key } = credentials.azureStorageSharedKeyApi; - const workflows = ['nodes/Microsoft/Storage/test/workflows/credentials_sharedKey.workflow.json']; - const workflowTests = workflowToTests(workflows); - - describe('should use correct shared key credentials', () => { - beforeEach(() => jest.restoreAllMocks()); - - for (const workflow of workflowTests) { - workflow.nock = { - baseUrl, - mocks: [ - { - method: 'get', - path: '/mycontainer?restype=container', - statusCode: 200, - responseBody: '', - responseHeaders: { - 'content-length': '0', - 'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT', - etag: '"0x8DD3FBA74CF3620"', - server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', - 'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000', - 'x-ms-version': '2020-10-02', - 'x-ms-lease-status': 'unlocked', - 'x-ms-lease-state': 'available', - 'x-ms-has-immutability-policy': 'false', - 'x-ms-has-legal-hold': 'false', - date: 'Wed, 29 Jan 2025 08:43:08 GMT', - 'x-ms-meta-key1': 'field1', - 'x-ms-blob-public-access': 'blob', - 'x-ms-lease-duration': 'infinite', - }, + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['credentials_sharedKey.workflow.json'], + nock: { + baseUrl, + mocks: [ + { + method: 'get', + path: '/mycontainer?restype=container', + statusCode: 200, + responseBody: '', + responseHeaders: { + 'content-length': '0', + 'last-modified': 'Tue, 28 Jan 2025 16:40:21 GMT', + etag: '"0x8DD3FBA74CF3620"', + server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0', + 'x-ms-request-id': '49edb268-b01e-0053-6e29-72d574000000', + 'x-ms-version': '2020-10-02', + 'x-ms-lease-status': 'unlocked', + 'x-ms-lease-state': 'available', + 'x-ms-has-immutability-policy': 'false', + 'x-ms-has-legal-hold': 'false', + date: 'Wed, 29 Jan 2025 08:43:08 GMT', + 'x-ms-meta-key1': 'field1', + 'x-ms-blob-public-access': 'blob', + 'x-ms-lease-duration': 'infinite', }, - ], - }; - workflow.credentials = credentials; - test(workflow.description, async () => await equalityTest(workflow)); - } + }, + ], + }, }); describe('authenticate', () => { diff --git a/packages/nodes-base/nodes/Microsoft/Storage/test/listSearch/listSearch.test.ts b/packages/nodes-base/nodes/Microsoft/Storage/test/listSearch/listSearch.test.ts index fac0086630..3cfcf204ec 100644 --- a/packages/nodes-base/nodes/Microsoft/Storage/test/listSearch/listSearch.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Storage/test/listSearch/listSearch.test.ts @@ -5,10 +5,11 @@ import { XMsVersion } from '../../GenericFunctions'; import { credentials } from '../credentials'; describe('Azure Storage Node', () => { + const { baseUrl } = credentials.azureStorageOAuth2Api; + describe('List search', () => { it('should list search blobs', async () => { - const mockResponse = - '1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMTmyblob2'; + const mockResponse = `1myblob1Wed, 22 Jan 2025 18:53:15 GMTWed, 22 Jan 2025 18:53:15 GMT0x1F8268B228AA73037application/jsonaWQGHD8kGQd5ZtEN/S1/aw==BlockBlobunlockedavailabletrueHottrueWed, 22 Jan 2025 18:53:15 GMTmyblob2`; const mockRequestWithAuthentication = jest.fn().mockReturnValue(mockResponse); const mockGetNodeParameter = jest.fn((parameterName, _fallbackValue, _options) => { if (parameterName === 'authentication') { @@ -43,7 +44,7 @@ describe('Azure Storage Node', () => { expect(mockRequestWithAuthentication).toHaveBeenCalledWith('azureStorageSharedKeyApi', { method: 'GET', - url: 'https://myaccount.blob.core.windows.net/mycontainer', + url: `${baseUrl}/mycontainer`, headers: { 'x-ms-date': 'Wed, 01 Jan 2025 00:00:00 GMT', 'x-ms-version': XMsVersion, @@ -63,8 +64,7 @@ describe('Azure Storage Node', () => { }); it('should list search containers', async () => { - const mockResponse = - 'mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1mycontainer2'; + const mockResponse = `mycontainer1mycontainer1true01DB7228F6BEE6E7Wed, 29 Jan 2025 08:37:00 GMT"0x8DD40401935032C"unlockedexpiredfalsefalsefalseWed, 29 Jan 2025 08:38:21 GMT7value1mycontainer2`; const mockRequestWithAuthentication = jest.fn().mockReturnValue(mockResponse); const mockGetNodeParameter = jest.fn((parameterName, _fallbackValue, _options) => { if (parameterName === 'authentication') { @@ -94,7 +94,7 @@ describe('Azure Storage Node', () => { expect(mockRequestWithAuthentication).toHaveBeenCalledWith('azureStorageSharedKeyApi', { method: 'GET', - url: 'https://myaccount.blob.core.windows.net/', + url: `${baseUrl}/`, headers: { 'x-ms-date': 'Wed, 01 Jan 2025 00:00:00 GMT', 'x-ms-version': XMsVersion, diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/create.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/create.test.ts index 238e7c6d4d..f43f901bb1 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channel => create', () => { @@ -21,6 +20,8 @@ describe('Test MicrosoftTeamsV2, channel => create', () => { membershipType: 'private', }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/create.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.test.ts index 44d4615953..4f2a338be4 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channel => deleteChannel', () => { @@ -11,6 +10,8 @@ describe('Test MicrosoftTeamsV2, channel => deleteChannel', () => { ) .reply(200, {}); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/deleteChannel.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['deleteChannel.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/get.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/get.test.ts index 1381955173..2e24a6bc4c 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channel => get', () => { @@ -24,6 +23,8 @@ describe('Test MicrosoftTeamsV2, channel => get', () => { membershipType: 'standard', }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/get.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/getAll.test.ts index 83d6657734..5ac6026983 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channel => getAll', () => { @@ -48,6 +47,8 @@ describe('Test MicrosoftTeamsV2, channel => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/getAll.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/update.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/update.test.ts index a9566e145b..9d4f91ef8e 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/update.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channel/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channel => update', () => { @@ -12,6 +11,8 @@ describe('Test MicrosoftTeamsV2, channel => update', () => { ) .reply(200, {}); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channel/update.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/create.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/create.test.ts index d01a548fef..31db80df7a 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channelMessage => create', () => { @@ -53,6 +52,8 @@ describe('Test MicrosoftTeamsV2, channelMessage => create', () => { reactions: [], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channelMessage/create.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.test.ts index 9f2ed49567..50feb0ab8c 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, channelMessage => getAll', () => { @@ -65,6 +64,8 @@ describe('Test MicrosoftTeamsV2, channelMessage => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/channelMessage/getAll.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/create.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/create.test.ts index 77fe592cc6..8b25a7a196 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, chatMessage => create', () => { @@ -47,6 +46,8 @@ describe('Test MicrosoftTeamsV2, chatMessage => create', () => { reactions: [], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/create.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/get.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/get.test.ts index a7db5a705e..0eccf14389 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, chatMessage => get', () => { @@ -48,6 +47,8 @@ describe('Test MicrosoftTeamsV2, chatMessage => get', () => { reactions: [], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/get.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.test.ts index 791ef01f3b..4b850a7abb 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, chatMessage => getAll', () => { @@ -88,6 +87,8 @@ describe('Test MicrosoftTeamsV2, chatMessage => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/chatMessage/getAll.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/create.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/create.test.ts index 7471469e80..b48b7ef910 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/create.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, task => create', () => { @@ -71,6 +70,8 @@ describe('Test MicrosoftTeamsV2, task => create', () => { }, }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/task/create.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/deleteTask.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/deleteTask.test.ts index 8d09b0050c..2706e18c60 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/deleteTask.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/deleteTask.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, task => deleteTask', () => { @@ -12,6 +11,8 @@ describe('Test MicrosoftTeamsV2, task => deleteTask', () => { .matchHeader('If-Match', 'W/"JzEtVGFzayAgQEBAQEBAQEBAQEBAQEBARCc="') .reply(200, {}); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/task/deleteTask.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['deleteTask.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/get.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/get.test.ts index aa901632e0..3cfd7254d6 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/get.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, task => get', () => { @@ -59,6 +58,8 @@ describe('Test MicrosoftTeamsV2, task => get', () => { }, }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/task/get.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/getAll.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/getAll.test.ts index 26774d9bdb..ffd021179a 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/getAll.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, task => getAll', () => { @@ -148,6 +147,8 @@ describe('Test MicrosoftTeamsV2, task => getAll', () => { ], }); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/task/getAll.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/update.test.ts b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/update.test.ts index 37bc10849d..f41be676c8 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/update.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/test/v2/node/task/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import { credentials } from '../../../credentials'; describe('Test MicrosoftTeamsV2, task => update', () => { @@ -16,6 +15,8 @@ describe('Test MicrosoftTeamsV2, task => update', () => { .matchHeader('If-Match', 'W/"JzEtVGFzayAgQEBAQEBAQEBAQEBAQEBARCc="') .reply(200); - const workflows = ['nodes/Microsoft/Teams/test/v2/node/task/update.workflow.json']; - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/MoveBinaryData/test/MoveBinaryData.test.ts b/packages/nodes-base/nodes/MoveBinaryData/test/MoveBinaryData.test.ts index 2aaf5c19ed..d0518c6cf0 100644 --- a/packages/nodes-base/nodes/MoveBinaryData/test/MoveBinaryData.test.ts +++ b/packages/nodes-base/nodes/MoveBinaryData/test/MoveBinaryData.test.ts @@ -1,24 +1,21 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import path from 'path'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Test Move Binary Data Node', () => { - const workflow = Helpers.readJsonFileSync( - 'nodes/MoveBinaryData/test/MoveBinaryData.workflow.json', - ); - const node = workflow.nodes.find((n: any) => n.name === 'Read Binary File'); + const testHarness = new NodeTestHarness(); + const workflowData = testHarness.readWorkflowJSON('MoveBinaryData.workflow.json'); + const node = workflowData.nodes.find((n) => n.name === 'Read Binary File')!; node.parameters.filePath = path.join(__dirname, 'data', 'sample.json'); const tests: WorkflowTestData[] = [ { description: 'nodes/MoveBinaryData/test/MoveBinaryData.workflow.json', input: { - workflowData: workflow, + workflowData, }, output: { + assertBinaryData: true, nodeData: { 'Binary to JSON': [ [ @@ -113,15 +110,6 @@ describe('Test Move Binary Data Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/MySql/test/v1/executeQuery.test.ts b/packages/nodes-base/nodes/MySql/test/v1/executeQuery.test.ts index f2f50bde9f..f1b76ae30b 100644 --- a/packages/nodes-base/nodes/MySql/test/v1/executeQuery.test.ts +++ b/packages/nodes-base/nodes/MySql/test/v1/executeQuery.test.ts @@ -1,9 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { mock } from 'jest-mock-extended'; import type { Connection, QueryResult } from 'mysql2/promise'; -import type { WorkflowTestData } from 'n8n-workflow'; - -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import { getResultNodeData, workflowToTests } from '@test/nodes/Helpers'; const mockConnection = mock(); const createConnection = jest.fn().mockReturnValue(mockConnection); @@ -12,27 +9,13 @@ jest.mock('mysql2/promise', () => ({ createConnection })); describe('Test MySqlV1, executeQuery', () => { mockConnection.query.mockResolvedValue([{ success: true } as unknown as QueryResult, []]); - const workflows = ['nodes/MySql/test/v1/executeQuery.workflow.json']; - const tests = workflowToTests(workflows); - - const testNode = async (testData: WorkflowTestData) => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = getResultNodeData(result, testData); - - resultNodeData.forEach(({ nodeName, resultData }) => { - return expect(resultData).toEqual(testData.output.nodeData[nodeName]); - }); - - expect(mockConnection.query).toHaveBeenCalledTimes(1); - expect(mockConnection.query).toHaveBeenCalledWith( - "select * from family_parents where (parent_email = 'parent1@mail.com' or parent_email = 'parent2@mail.com') and parent_email <> '';", - ); - - expect(result.finished).toEqual(true); - }; - - for (const testData of tests) { - test(testData.description, async () => await testNode(testData)); - } + new NodeTestHarness().setupTests({ + workflowFiles: ['executeQuery.workflow.json'], + customAssertions() { + expect(mockConnection.query).toHaveBeenCalledTimes(1); + expect(mockConnection.query).toHaveBeenCalledWith( + "select * from family_parents where (parent_email = 'parent1@mail.com' or parent_email = 'parent2@mail.com') and parent_email <> '';", + ); + }, + }); }); diff --git a/packages/nodes-base/nodes/N8n/test/node/N8n.test.ts b/packages/nodes-base/nodes/N8n/test/node/N8n.test.ts index a9735461ff..b007c9ca25 100644 --- a/packages/nodes-base/nodes/N8n/test/node/N8n.test.ts +++ b/packages/nodes-base/nodes/N8n/test/node/N8n.test.ts @@ -1,33 +1,20 @@ -import type { WorkflowTestData } from 'n8n-workflow'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import { workflowToTests, getWorkflowFilenames } from '@test/nodes/Helpers'; - -describe('Test N8n Node, expect base_url to be received from credentials', () => { +describe('Test N8n Node', () => { + const baseUrl = 'https://test.app.n8n.cloud/api/v1'; const credentials = { n8nApi: { apiKey: 'key123', - baseUrl: 'https://test.app.n8n.cloud/api/v1', + baseUrl, }, }; - const workflows = getWorkflowFilenames(__dirname); - const tests = workflowToTests(workflows, credentials); - - beforeAll(() => { - //base url is set in fake credentials map packages/nodes-base/test/nodes/FakeCredentialsMap.ts - const { baseUrl } = credentials.n8nApi; - nock(baseUrl).get('/workflows?tags=n8n-test').reply(200, {}); + beforeAll(async () => { + const { pinData } = await import('./workflow.n8n.workflows.json'); + const apiResponse = pinData.n8n.map((item) => item.json); + nock(baseUrl).get('/workflows?tags=n8n-test').reply(200, { data: apiResponse }); }); - const testNode = async (testData: WorkflowTestData) => { - const { result } = await executeWorkflow(testData); - - expect(result.finished).toEqual(true); - }; - - for (const testData of tests) { - test(testData.description, async () => await testNode(testData)); - } + new NodeTestHarness().setupTests({ credentials }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/block/append.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/block/append.test.ts index 205664cc9b..79fd7342eb 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/block/append.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/block/append.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'list', results: [ @@ -416,6 +415,7 @@ describe('Test NotionV2, block => append', () => { .patch('/v1/blocks/90e03468f8aa457695da02ccad963040/children') .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/block/append.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['append.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/block/getAll.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/block/getAll.test.ts index c5c887b185..b08db00934 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/block/getAll.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/block/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { results: [ { @@ -215,6 +214,7 @@ describe('Test NotionV2, block => getAll', () => { .get('/v1/blocks/90e03468f8aa457695da02ccad963040/children') .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/block/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/database/get.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/database/get.test.ts index bcb91a6b58..3595cf2d40 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/database/get.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/database/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'database', id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f', @@ -70,6 +69,7 @@ describe('Test NotionV2, database => get', () => { .get('/v1/databases/138fb9cb-4cf0-804c-8663-d8ecdd5e692f') .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/database/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/database/getAll.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/database/getAll.test.ts index 99e1c4fde4..14f9264028 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/database/getAll.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/database/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { results: [ { @@ -314,6 +313,7 @@ describe('Test NotionV2, database => getAll', () => { .post('/v1/search', { filter: { property: 'object', value: 'database' } }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/database/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/database/search.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/database/search.test.ts index 74cfc44eab..b859eecf95 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/database/search.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/database/search.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { results: [ { @@ -192,6 +191,7 @@ describe('Test NotionV2, database => search', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/database/search.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['search.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/create.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/create.test.ts index 4820339649..a91d063970 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/create.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'page', id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3', @@ -101,6 +100,7 @@ describe('Test NotionV2, databasePage => create', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/databasePage/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/get.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/get.test.ts index cfdd875161..bb96849b4a 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/get.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'page', id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3', @@ -66,6 +65,7 @@ describe('Test NotionV2, databasePage => get', () => { .get('/v1/pages/15bfb9cb4cf081c7aab4c5855b8cb6c3') .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/databasePage/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/getAll.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/getAll.test.ts index 64571a5bf2..345d35c659 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/getAll.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { results: [ { @@ -73,6 +72,7 @@ describe('Test NotionV2, databasePage => getAll', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/databasePage/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/update.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/update.test.ts index b7f3ae3440..07c06b2f2a 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/update.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/databasePage/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'page', id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3', @@ -68,6 +67,7 @@ describe('Test NotionV2, databasePage => update', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/databasePage/update.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/page/archive.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/page/archive.test.ts index 9d8a004fcd..ebc854a470 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/page/archive.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/page/archive.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'page', id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3', @@ -66,6 +65,7 @@ describe('Test NotionV2, page => archive', () => { .patch('/v1/pages/15bfb9cb4cf081c7aab4c5855b8cb6c3', { archived: true }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/page/archive.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['archive.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/page/create.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/page/create.test.ts index 2f1101d008..4bd4af10a1 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/page/create.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/page/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'page', id: '15bfb9cb-4cf0-812b-b4bc-c85cd00727f8', @@ -77,6 +76,7 @@ describe('Test NotionV2, page => create', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/page/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/page/search.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/page/search.test.ts index ad359d039a..8430559414 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/page/search.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/page/search.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { results: [ { @@ -69,6 +68,7 @@ describe('Test NotionV2, page => search', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/page/search.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['search.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/user/get.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/user/get.test.ts index 695f9d07e0..7673ff51e9 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/user/get.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/user/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { object: 'user', id: '34a945c6-de97-4efc-90d6-6d7cc14a6583', @@ -17,6 +16,7 @@ describe('Test NotionV2, user => get', () => { .get('/v1/users/34a945c6-de97-4efc-90d6-6d7cc14a6583') .reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/user/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Notion/test/node/v2/user/getAll.test.ts b/packages/nodes-base/nodes/Notion/test/node/v2/user/getAll.test.ts index 3182dd49e0..9f0c8b15fc 100644 --- a/packages/nodes-base/nodes/Notion/test/node/v2/user/getAll.test.ts +++ b/packages/nodes-base/nodes/Notion/test/node/v2/user/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { results: [ { @@ -42,6 +41,7 @@ const API_RESPONSE = { describe('Test NotionV2, user => getAll', () => { nock('https://api.notion.com').get('/v1/users').reply(200, API_RESPONSE); - const workflows = ['nodes/Notion/test/node/v2/user/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Npm/test/Npm.node.test.ts b/packages/nodes-base/nodes/Npm/test/Npm.node.test.ts index 71c7af6b42..b6146523e6 100644 --- a/packages/nodes-base/nodes/Npm/test/Npm.node.test.ts +++ b/packages/nodes-base/nodes/Npm/test/Npm.node.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - describe('Test npm Node', () => { const credentials = { npmApi: { @@ -34,6 +33,5 @@ describe('Test npm Node', () => { }); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); diff --git a/packages/nodes-base/nodes/OpenWeatherMap/test/OpenWeatherMap.test.ts b/packages/nodes-base/nodes/OpenWeatherMap/test/OpenWeatherMap.test.ts index d9ad280b34..3a3b248c93 100644 --- a/packages/nodes-base/nodes/OpenWeatherMap/test/OpenWeatherMap.test.ts +++ b/packages/nodes-base/nodes/OpenWeatherMap/test/OpenWeatherMap.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { currentWeatherResponse } from './apiResponses'; describe('OpenWeatherMap', () => { @@ -13,7 +12,6 @@ describe('OpenWeatherMap', () => { .reply(200, currentWeatherResponse); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); }); diff --git a/packages/nodes-base/nodes/Oura/test/oura.node.test.ts b/packages/nodes-base/nodes/Oura/test/oura.node.test.ts index a010b97884..97e6b04cd0 100644 --- a/packages/nodes-base/nodes/Oura/test/oura.node.test.ts +++ b/packages/nodes-base/nodes/Oura/test/oura.node.test.ts @@ -1,3 +1,4 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { IExecuteFunctions, IHookFunctions, @@ -7,8 +8,6 @@ import type { } from 'n8n-workflow'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { profileResponse } from './apiResponses'; import { ouraApiRequest } from '../GenericFunctions'; @@ -51,6 +50,7 @@ describe('Oura', () => { }); }); }); + describe('Run Oura workflow', () => { beforeAll(() => { nock('https://api.ouraring.com/v2') @@ -58,7 +58,6 @@ describe('Oura', () => { .reply(200, profileResponse); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); }); diff --git a/packages/nodes-base/nodes/Peekalink/test/Peekalink.node.test.ts b/packages/nodes-base/nodes/Peekalink/test/Peekalink.node.test.ts index 2827260e65..22c0b04c93 100644 --- a/packages/nodes-base/nodes/Peekalink/test/Peekalink.node.test.ts +++ b/packages/nodes-base/nodes/Peekalink/test/Peekalink.node.test.ts @@ -1,11 +1,10 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - import { apiUrl } from '../Peekalink.node'; describe('Peekalink Node', () => { + const testHarness = new NodeTestHarness(); const exampleComPreview = { url: 'https://example.com/', domain: 'example.com', @@ -69,7 +68,6 @@ describe('Peekalink Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Peekalink: [ [ @@ -141,7 +139,6 @@ describe('Peekalink Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], nodeData: { Peekalink: [ [ @@ -166,12 +163,7 @@ describe('Peekalink Node', () => { }, ]; - test.each(tests)('$description', async (testData) => { - const { result } = await executeWorkflow(testData); - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - expect(result.finished).toEqual(true); - }); + for (const testData of tests) { + testHarness.setupTest(testData); + } }); diff --git a/packages/nodes-base/nodes/PhilipsHue/test/workflow.test.ts b/packages/nodes-base/nodes/PhilipsHue/test/workflow.test.ts index 1240afdda1..e633077c00 100644 --- a/packages/nodes-base/nodes/PhilipsHue/test/workflow.test.ts +++ b/packages/nodes-base/nodes/PhilipsHue/test/workflow.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { deleteLightResponse, getLightsResponse, @@ -38,7 +37,6 @@ describe('PhilipsHue', () => { mock.delete('/api/pAtwdCV8NZId25Gk/lights/1').reply(200, deleteLightResponse); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/QuickChart/test/QuickChart.node.test.ts b/packages/nodes-base/nodes/QuickChart/test/QuickChart.node.test.ts index d63fb157c7..d07168205d 100644 --- a/packages/nodes-base/nodes/QuickChart/test/QuickChart.node.test.ts +++ b/packages/nodes-base/nodes/QuickChart/test/QuickChart.node.test.ts @@ -1,10 +1,7 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import nock from 'nock'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Test QuickChart Node', () => { beforeEach(async () => { nock('https://quickchart.io') @@ -13,13 +10,12 @@ describe('Test QuickChart Node', () => { .reply(200, { success: true }); }); - const workflow = Helpers.readJsonFileSync('nodes/QuickChart/test/QuickChart.workflow.json'); - + const testHarness = new NodeTestHarness(); const tests: WorkflowTestData[] = [ { description: 'nodes/QuickChart/test/QuickChart.workflow.json', input: { - workflowData: workflow, + workflowData: testHarness.readWorkflowJSON('QuickChart.workflow.json'), }, output: { nodeData: { @@ -89,15 +85,6 @@ describe('Test QuickChart Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => { - delete resultData[0]![0].binary; - expect(resultData).toEqual(testData.output.nodeData[nodeName]); - }); - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/ReadBinaryFile/test/ReadBinaryFile.test.ts b/packages/nodes-base/nodes/ReadBinaryFile/test/ReadBinaryFile.test.ts index 376a13bb94..f42c47780d 100644 --- a/packages/nodes-base/nodes/ReadBinaryFile/test/ReadBinaryFile.test.ts +++ b/packages/nodes-base/nodes/ReadBinaryFile/test/ReadBinaryFile.test.ts @@ -1,24 +1,21 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import path from 'path'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Test Read Binary File Node', () => { - const workflow = Helpers.readJsonFileSync( - 'nodes/ReadBinaryFile/test/ReadBinaryFile.workflow.json', - ); - const node = workflow.nodes.find((n: any) => n.name === 'Read Binary File'); + const testHarness = new NodeTestHarness(); + const workflowData = testHarness.readWorkflowJSON('ReadBinaryFile.workflow.json'); + const node = workflowData.nodes.find((n) => n.name === 'Read Binary File')!; node.parameters.filePath = path.join(__dirname, 'image.jpg'); const tests: WorkflowTestData[] = [ { description: 'nodes/ReadBinaryFile/test/ReadBinaryFile.workflow.json', input: { - workflowData: workflow, + workflowData, }, output: { + assertBinaryData: true, nodeData: { 'Read Binary File': [ [ @@ -30,7 +27,6 @@ describe('Test Read Binary File Node', () => { fileType: 'image', fileExtension: 'jpg', data: '/9j/4AAQSkZJRgABAQEASABIAAD/4QBmRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAAQAAAATgAAAAAAARlJAAAD6AABGUkAAAPocGFpbnQubmV0IDUuMC4xAP/bAEMAIBYYHBgUIBwaHCQiICYwUDQwLCwwYkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxv/bAEMBIiQkMCowXjQ0XsaEcITGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxv/AABEIAB8AOwMBEgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOgqgrXF2zNHJ5aKcD3oNPZ23di/VKG82bkuTh1OMgdaAdOSLtZ6G5ut0iSeWoOAKAdO27NCqUN8oQrcHDqccDrQDpyRNPdRwEKcsx7CobIebPLORwThc0inGMF724jagNpxG4OOM1dIDAgjIPBpkqUOxnR2pmh85pW3nJB9KkNi4yqTssZ6rSNXNX0ehHFfusYDLuI7+tXY4I40ChQcdzQRKcL7Fb7PcQO32cqUY5we1XqZPtH11KsFoFDGYK7sckkZxVqgTnJlEQXMBZYGUoTkZ7VeoH7RvcqwWaIh80K7k5JIq1QJzkyhbMtvdSxMdqnlc1amgjmx5i5I70inNSVpFdrmaWRltkBVerHvUW57B2AUNGxyOaC+VW9xXLVrcGbcjrtkXqKZZxvveeTAL9APSgiooq1ty3RTMj//2Q==', - directory: __dirname, fileName: 'image.jpg', fileSize: '1.04 kB', }, @@ -44,15 +40,6 @@ describe('Test Read Binary File Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/ReadBinaryFiles/test/ReadBinaryFiles.test.ts b/packages/nodes-base/nodes/ReadBinaryFiles/test/ReadBinaryFiles.test.ts index 9e407f45da..acda8ffda6 100644 --- a/packages/nodes-base/nodes/ReadBinaryFiles/test/ReadBinaryFiles.test.ts +++ b/packages/nodes-base/nodes/ReadBinaryFiles/test/ReadBinaryFiles.test.ts @@ -1,15 +1,11 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import path from 'path'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Test Read Binary Files Node', () => { - const workflow = Helpers.readJsonFileSync( - 'nodes/ReadBinaryFiles/test/ReadBinaryFiles.workflow.json', - ); - const node = workflow.nodes.find((n: any) => n.name === 'Read Binary Files'); + const testHarness = new NodeTestHarness(); + const workflowData = testHarness.readWorkflowJSON('ReadBinaryFiles.workflow.json'); + const node = workflowData.nodes.find((n) => n.name === 'Read Binary Files')!; const dir = path.join(__dirname, 'data').split('\\').join('/'); node.parameters.fileSelector = `${dir}/*.json`; @@ -17,9 +13,10 @@ describe('Test Read Binary Files Node', () => { { description: 'nodes/ReadBinaryFiles/test/ReadBinaryFiles.workflow.json', input: { - workflowData: workflow, + workflowData, }, output: { + assertBinaryData: true, nodeData: { 'Read Binary Files': [ [ @@ -30,7 +27,6 @@ describe('Test Read Binary Files Node', () => { fileType: 'json', fileExtension: 'json', data: 'ewoJInRpdGxlIjogIkxvcmVtIElwc3VtIgp9Cg==', - directory: dir, fileName: 'sample.json', fileSize: '28 B', }, @@ -44,7 +40,6 @@ describe('Test Read Binary Files Node', () => { fileType: 'json', fileExtension: 'json', data: 'ewoJInRpdGxlIjogIklwc3VtIExvcmVtIgp9Cg==', - directory: dir, fileName: 'sample2.json', fileSize: '28 B', }, @@ -59,15 +54,6 @@ describe('Test Read Binary Files Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json index 1bf9f597b8..f46f9f7f98 100644 --- a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json +++ b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json @@ -32,6 +32,7 @@ { "binary": { "data": { + "data": "JVBERi0xLjcKJb/3ov4KMSAwIG9iago8PCAvRGVzdHMgMyAwIFIgL0V4dGVuc2lvbnMgPDwgL0FEQkUgPDwgL0Jhc2VWZXJzaW9uIC8xLjcgL0V4dGVuc2lvbkxldmVsIDggPj4gPj4gL1BhZ2VzIDQgMCBSIC9UeXBlIC9DYXRhbG9nID4+CmVuZG9iagoyIDAgb2JqCjw8IC9Nb2REYXRlIDxiNWY4ZTdmY2U0M2IwMjEyYWNmY2ZlZmRkMDczYmI2OWI2YzViZWY5NDUxYmQ2OTE3NWNjNjQ2MWE0MzhmZWNlYjY4ZTE5MWU0YjBjNDI1YjQ4M2E4YzE1N2ZkMTA2ODk+IC9Qcm9kdWNlciA8YjUxZjdjNjcwNzE3MzI0MDlkNTFmNzQzYTgzNjcwMWVjNzk3NzVjMTZhNjhlMTNhMzcxOTY0NTdhMTEyODYzYz4gL1RpdGxlIDxiMWEzNzhiNzQ0OTkzMzEzNzVkMTJiYjZmMjYwYjhhOTI3OWRkMjVhODBhODg2ZGJlYTg5N2ExZTIxMDM3ZWQxPiA+PgplbmRvYmoKMyAwIG9iago8PCAvaC5lcGhqNjhzYjV5c2kgWyA1IDAgUiAvWFlaIDcyIDcyMCAwIF0gL2gubm45aTJxaXZhdGx4IFsgNSAwIFIgL1hZWiA3MiA2ODIuNjE4IDAgXSA+PgplbmRvYmoKNCAwIG9iago8PCAvQ291bnQgMSAvS2lkcyBbIDUgMCBSIF0gL1R5cGUgL1BhZ2VzID4+CmVuZG9iago1IDAgb2JqCjw8IC9Db250ZW50cyA2IDAgUiAvTWVkaWFCb3ggWyAwIDAgNjEyIDc5MiBdIC9QYXJlbnQgNCAwIFIgL1Jlc291cmNlcyA8PCAvRXh0R1N0YXRlIDw8IC9HMyA3IDAgUiA+PiAvRm9udCA8PCAvRjQgOCAwIFIgPj4gPj4gL1R5cGUgL1BhZ2UgPj4KZW5kb2JqCjYgMCBvYmoKPDwgL0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCA2ODggPj4Kc3RyZWFtCjPr0WuJUoe2MNgz0I9MoibKBawXCPGfablRvyaxSbwx14vBL2K/IjhZCjv/bqhJ0jt+OsvOBtAj2nlsoDsDhch+a8D/6qmnMn1yegiQILVcjLW8+BI9f/ojh7WaDW4jSQTFAlJvYhPE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MGE4ZWE1YmY3MDFjMzhiNGY1MzM5NzI5OGExNWIzYjQxYTgzODFmOWZkZmQ3YjMyYTNjMWU5YTgyNzc5MjlhNjc5OWEzNjQ+IC9PRSA8ZWNhMDE4YzBlNWE3YzFjMWI0NTJiZmJhN2RiNjhjYmE5YjFjNjdkZThmMjFiY2M5ZWQyMmFhZjE3MDg1ZDhhZT4gL1AgLTQgL1Blcm1zIDwyOWFlZTY5NjIxZTljYjRkNzE5ZTAyYTJhMDVhMjhjNz4gL1IgNiAvU3RtRiAvU3RkQ0YgL1N0ckYgL1N0ZENGIC9VIDw4NjJkNjdkMzIxYWI5Y2UyYjQxNDJiYmQ5MzVjM2M3YzU2YWQ3Y2MzZDkwMmUzYzUwYmEwYTAzOWQ5ZGQ0ZmY0ZTVjMTk3YTI0NmE0NDg4M2Y3NGZhODIwMGRlNDlmNWE+IC9VRSA8NTUzMTRhODk1YTQ1N2I5ZWJjMWRjYTUwYmQ3MTkyNWY4ODMzZmU2NTI0MzJiNDM3MDUzMjhkOTExZTIxNDgyNT4gL1YgNSA+PgplbmRvYmoKeHJlZgowIDE0CjAwMDAwMDAwMDAgNjU1MzUgZiAKMDAwMDAwMDAxNSAwMDAwMCBuIAowMDAwMDAwMTQzIDAwMDAwIG4gCjAwMDAwMDA0MjMgMDAwMDAgbiAKMDAwMDAwMDUyOCAwMDAwMCBuIAowMDAwMDAwNTg3IDAwMDAwIG4gCjAwMDAwMDA3NDIgMDAwMDAgbiAKMDAwMDAwMTUwMSAwMDAwMCBuIAowMDAwMDAxNTQwIDAwMDAwIG4gCjAwMDAwMDE2ODIgMDAwMDAgbiAKMDAwMDAwMjI2MiAwMDAwMCBuIAowMDAwMDAyNjcwIDAwMDAwIG4gCjAwMDAwMDI4OTQgMDAwMDAgbiAKMDAwMDAxNzg2MyAwMDAwMCBuIAp0cmFpbGVyIDw8IC9JbmZvIDIgMCBSIC9Sb290IDEgMCBSIC9TaXplIDE0IC9JRCBbPDU1YjM2YmQxMTE5OWRjYmM5YTMyZTEzMmFiMDY3YzZhPjw5YjFkMmYwMDA1MmMxNjBiNzYxNzFmYTk1ZWNjMGEwNz5dIC9FbmNyeXB0IDEzIDAgUiA+PgpzdGFydHhyZWYKMTg0MTEKJSVFT0YK", "fileExtension": "pdf", "fileName": "sample-encrypted.pdf", "fileSize": "18.9 kB", diff --git a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.test.ts b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.test.ts index 492724df16..ede4fcbf99 100644 --- a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.test.ts +++ b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.test.ts @@ -1,7 +1,5 @@ -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; describe('Test Read PDF Node', () => { - const workflows = getWorkflowFilenames(__dirname); - - testWorkflows(workflows); + new NodeTestHarness().setupTests({ assertBinaryData: true }); }); diff --git a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json index 5b257711ad..216795a03b 100644 --- a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json +++ b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json @@ -29,6 +29,7 @@ { "binary": { "data": { + "data": "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PAovaC5lcGhqNjhzYjV5c2kgWzQgMCBSIC9YWVogNzIgNzIwIDBdCi9oLm5uOWkycWl2YXRseCBbNCAwIFIgL1hZWiA3MiA2ODIuNjE4IDBdCj4+CmVuZG9iagoyIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwovS2lkcyBbNCAwIFJdCi9Db3VudCAxCj4+CmVuZG9iagoxIDAgb2JqCjw8Ci9UeXBlIC9DYXRhbG9nCi9QYWdlcyAyIDAgUgovRGVzdHMgMTIgMCBSCj4+CmVuZG9iagozIDAgb2JqCjw8Ci9UaXRsZSAoc2FtcGxlKQovUHJvZHVjZXIgKGlMb3ZlUERGKQovTW9kRGF0ZSAoRDoyMDIzMDIxMDEyMjc1MFopCj4+CmVuZG9iagp4cmVmCjAgMTMKMDAwMDAwMDAwMCA2NTUzNSBmDQowMDAwMDE3MjQ5IDAwMDAwIG4NCjAwMDAwMTcxOTIgMDAwMDAgbg0KMDAwMDAxNzMxMiAwMDAwMCBuDQowMDAwMDE2OTM3IDAwMDAwIG4NCjAwMDAwMTYyMDUgMDAwMDAgbg0KMDAwMDAwMDAxNSAwMDAwMCBuDQowMDAwMDE2MDY1IDAwMDAwIG4NCjAwMDAwMTUyMjUgMDAwMDAgbg0KMDAwMDAxNTAwNCAwMDAwMCBuDQowMDAwMDAwMDU0IDAwMDAwIG4NCjAwMDAwMTU2NzMgMDAwMDAgbg0KMDAwMDAxNzA5MCAwMDAwMCBuDQp0cmFpbGVyCjw8Ci9TaXplIDEzCi9Sb290IDEgMCBSCi9JbmZvIDMgMCBSCi9JRCBbPDU1QjM2QkQxMTE5OURDQkM5QTMyRTEzMkFCMDY3QzZBPiA8OEYyODQ0NDMyMjZDRjcyNTk4MzMwQkE5NjNDMjAyQkE+XQo+PgpzdGFydHhyZWYKMTczOTkKJSVFT0YK", "fileExtension": "pdf", "fileName": "sample.pdf", "fileSize": "17.8 kB", diff --git a/packages/nodes-base/nodes/RenameKeys/test/RenameKeys.test.ts b/packages/nodes-base/nodes/RenameKeys/test/RenameKeys.test.ts index deb62b4ac9..01cb32f5d9 100644 --- a/packages/nodes-base/nodes/RenameKeys/test/RenameKeys.test.ts +++ b/packages/nodes-base/nodes/RenameKeys/test/RenameKeys.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Rename Keys Node', () => testWorkflows(workflows)); +describe('Test Rename Keys Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/RssFeedRead/test/node/RssFeedRead.test.ts b/packages/nodes-base/nodes/RssFeedRead/test/node/RssFeedRead.test.ts index a5d99fad49..08f5b4a9d6 100644 --- a/packages/nodes-base/nodes/RssFeedRead/test/node/RssFeedRead.test.ts +++ b/packages/nodes-base/nodes/RssFeedRead/test/node/RssFeedRead.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - // eslint-disable-next-line n8n-local-rules/no-unneeded-backticks const feed = `<![CDATA[Lorem ipsum feed for an interval of 1 minutes with 3 item(s)]]>http://example.com/RSS for NodeThu, 09 Feb 2023 13:40:32 GMTThu, 09 Feb 2023 13:40:00 GMT1<![CDATA[Lorem ipsum 2023-02-09T13:40:00Z]]>http://example.com/test/1675950000http://example.com/test/1675950000Thu, 09 Feb 2023 13:40:00 GMT<![CDATA[Lorem ipsum 2023-02-09T13:39:00Z]]>http://example.com/test/1675949940http://example.com/test/1675949940Thu, 09 Feb 2023 13:39:00 GMT<![CDATA[Lorem ipsum 2023-02-09T13:38:00Z]]>http://example.com/test/1675949880http://example.com/test/1675949880Thu, 09 Feb 2023 13:38:00 GMT`; @@ -10,6 +9,5 @@ describe('Test RSS Feed Trigger Node', () => { nock('https://lorem-rss.herokuapp.com').get('/feed?length=3').reply(200, feed); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/Salesforce/__test__/node/Salesforce.node.test.ts b/packages/nodes-base/nodes/Salesforce/__test__/node/Salesforce.node.test.ts index 808e480370..8253d955b4 100644 --- a/packages/nodes-base/nodes/Salesforce/__test__/node/Salesforce.node.test.ts +++ b/packages/nodes-base/nodes/Salesforce/__test__/node/Salesforce.node.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - import accountDetails from './fixtures/account-details.json'; import accounts from './fixtures/accounts.json'; import opportunitiesSummary from './fixtures/opportunities-summary.json'; @@ -40,7 +39,10 @@ describe('Salesforce Node', () => { afterAll(() => salesforceNock.done()); - testWorkflows(['nodes/Salesforce/__test__/node/users.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['users.workflow.json'], + }); }); describe('tasks', () => { @@ -69,7 +71,10 @@ describe('Salesforce Node', () => { afterAll(() => salesforceNock.done()); - testWorkflows(['nodes/Salesforce/__test__/node/tasks.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['tasks.workflow.json'], + }); }); describe('accounts', () => { @@ -100,7 +105,10 @@ describe('Salesforce Node', () => { afterAll(() => salesforceNock.done()); - testWorkflows(['nodes/Salesforce/__test__/node/accounts.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['accounts.workflow.json'], + }); }); describe('search', () => { @@ -115,7 +123,10 @@ describe('Salesforce Node', () => { afterAll(() => salesforceNock.done()); - testWorkflows(['nodes/Salesforce/__test__/node/search.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['search.workflow.json'], + }); }); describe('opportunities', () => { @@ -156,6 +167,9 @@ describe('Salesforce Node', () => { afterAll(() => salesforceNock.done()); - testWorkflows(['nodes/Salesforce/__test__/node/opportunities.workflow.json'], credentials); + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['opportunities.workflow.json'], + }); }); }); diff --git a/packages/nodes-base/nodes/SeaTable/v2/actions/asset/upload.operation.ts b/packages/nodes-base/nodes/SeaTable/v2/actions/asset/upload.operation.ts index fee1671db5..c8447f75ae 100644 --- a/packages/nodes-base/nodes/SeaTable/v2/actions/asset/upload.operation.ts +++ b/packages/nodes-base/nodes/SeaTable/v2/actions/asset/upload.operation.ts @@ -117,7 +117,7 @@ export async function execute( const relativePath = uploadColumnType === 'image' ? uploadLink.img_relative_path : uploadLink.file_relative_path; - const options = this.getNodeParameter('options', index) as IDataObject; + const options = this.getNodeParameter('options', index); // get server url const credentials: any = await this.getCredentials('seaTableApi'); diff --git a/packages/nodes-base/nodes/SeaTable/v2/actions/row/get.operation.ts b/packages/nodes-base/nodes/SeaTable/v2/actions/row/get.operation.ts index 692fa8b62a..64200b6c77 100644 --- a/packages/nodes-base/nodes/SeaTable/v2/actions/row/get.operation.ts +++ b/packages/nodes-base/nodes/SeaTable/v2/actions/row/get.operation.ts @@ -57,7 +57,7 @@ export async function execute( // get parameters const tableName = this.getNodeParameter('tableName', index) as string; const rowId = this.getNodeParameter('rowId', index) as string; - const options = this.getNodeParameter('options', index) as IDataObject; + const options = this.getNodeParameter('options', index); // get collaborators const collaborators = await getBaseCollaborators.call(this); diff --git a/packages/nodes-base/nodes/SeaTable/v2/actions/row/list.operation.ts b/packages/nodes-base/nodes/SeaTable/v2/actions/row/list.operation.ts index 7dc9082502..8efedc7045 100644 --- a/packages/nodes-base/nodes/SeaTable/v2/actions/row/list.operation.ts +++ b/packages/nodes-base/nodes/SeaTable/v2/actions/row/list.operation.ts @@ -71,7 +71,7 @@ export async function execute( // get parameters const tableName = this.getNodeParameter('tableName', index) as string; const viewName = this.getNodeParameter('viewName', index) as string; - const options = this.getNodeParameter('options', index) as IDataObject; + const options = this.getNodeParameter('options', index); // get collaborators const collaborators = await getBaseCollaborators.call(this); diff --git a/packages/nodes-base/nodes/SeaTable/v2/actions/row/search.operation.ts b/packages/nodes-base/nodes/SeaTable/v2/actions/row/search.operation.ts index d0a8f482a0..82dd048028 100644 --- a/packages/nodes-base/nodes/SeaTable/v2/actions/row/search.operation.ts +++ b/packages/nodes-base/nodes/SeaTable/v2/actions/row/search.operation.ts @@ -96,7 +96,7 @@ export async function execute( const searchColumn = this.getNodeParameter('searchColumn', index) as string; const searchTerm = this.getNodeParameter('searchTerm', index) as string | number; let searchTermString = String(searchTerm); - const options = this.getNodeParameter('options', index) as IDataObject; + const options = this.getNodeParameter('options', index); // get collaborators const collaborators = await getBaseCollaborators.call(this); diff --git a/packages/nodes-base/nodes/SendGrid/test/SendGrid.node.test.ts b/packages/nodes-base/nodes/SendGrid/test/SendGrid.node.test.ts index e7ba0d647e..3590f5b400 100644 --- a/packages/nodes-base/nodes/SendGrid/test/SendGrid.node.test.ts +++ b/packages/nodes-base/nodes/SendGrid/test/SendGrid.node.test.ts @@ -1,8 +1,7 @@ /* eslint-disable n8n-nodes-base/node-param-display-name-miscased */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test SendGrid Node', () => { describe('Mail', () => { const sendgridNock = nock('https://api.sendgrid.com/v3') @@ -15,6 +14,8 @@ describe('Test SendGrid Node', () => { afterAll(() => sendgridNock.done()); - testWorkflows(['nodes/SendGrid/test/mail.workflow.json']); + new NodeTestHarness().setupTests({ + workflowFiles: ['mail.workflow.json'], + }); }); }); diff --git a/packages/nodes-base/nodes/Set/test/Set.node.test.ts b/packages/nodes-base/nodes/Set/test/Set.node.test.ts index 121a3c0a12..1a933778db 100644 --- a/packages/nodes-base/nodes/Set/test/Set.node.test.ts +++ b/packages/nodes-base/nodes/Set/test/Set.node.test.ts @@ -1,4 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; -const workflows = getWorkflowFilenames(__dirname); +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -describe('Test Set Node', () => testWorkflows(workflows)); +describe('Test Set Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/channel/archive.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/channel/archive.test.ts index 2eef606aa1..899ea0585a 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/channel/archive.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/channel/archive.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, }; @@ -9,6 +8,7 @@ const API_RESPONSE = { describe('Test SlackV2, channel => append', () => { nock('https://slack.com').post('/api/conversations.archive').reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/channel/archive.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['archive.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/channel/create.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/channel/create.test.ts index 8719913051..f651bf0c79 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/channel/create.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/channel/create.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, channel: { @@ -48,6 +47,7 @@ const API_RESPONSE = { describe('Test SlackV2, channel => create', () => { nock('https://slack.com').post('/api/conversations.create').reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/channel/create.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['create.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/channel/get.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/channel/get.test.ts index a53a17e876..c7e5bfcb74 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/channel/get.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/channel/get.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, channel: { @@ -49,6 +48,7 @@ describe('Test SlackV2, channel => get', () => { .post('/api/conversations.info?channel=C085WNEHP4Y') .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/channel/get.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['get.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/channel/getAll.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/channel/getAll.test.ts index 68f7f15c59..20c6f01d06 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/channel/getAll.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/channel/getAll.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, channels: [ @@ -114,6 +113,7 @@ describe('Test SlackV2, channel => getAll', () => { ) .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/channel/getAll.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getAll.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/channel/history.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/channel/history.test.ts index 31d44c6eef..ec0ed8e1f2 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/channel/history.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/channel/history.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, messages: [ @@ -171,6 +170,7 @@ describe('Test SlackV2, channel => history', () => { .get('/api/conversations.history?channel=C08514ZPKB8&inclusive=true&page=1&limit=100') .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/channel/history.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['history.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/file/upload.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/file/upload.test.ts index 61832a8390..b0aa3681fd 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/file/upload.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/file/upload.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test SlackV2, file => upload', () => { nock('https://slack.com') .get('/api/files.getUploadURLExternal?filename=test%20_name.txt&length=25') @@ -11,6 +10,7 @@ describe('Test SlackV2, file => upload', () => { .post('/api/files.completeUploadExternal') .reply(200, { ok: true, files: [{ id: 'file_id' }] }); - const workflows = ['nodes/Slack/test/v2/node/file/upload.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['upload.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/message/delete.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/message/delete.test.ts index 00aa3c56ea..d3eeb5c371 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/message/delete.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/message/delete.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, channel: 'C08514ZPKB8', @@ -11,6 +10,7 @@ const API_RESPONSE = { describe('Test SlackV2, message => delete', () => { nock('https://slack.com').post('/api/chat.delete').reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/message/delete.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['delete.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/message/getPermalink.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/message/getPermalink.test.ts index 868d040343..55b3626194 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/message/getPermalink.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/message/getPermalink.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, permalink: 'https://myspace-qhg7381.slack.com/archives/C08514ZPKB8/p1734322671726339', @@ -13,6 +12,7 @@ describe('Test SlackV2, message => getPermalink', () => { .get('/api/chat.getPermalink?channel=C08514ZPKB8&message_ts=1734322671.726339') .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/message/getPermalink.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['getPermalink.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/message/post.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/message/post.test.ts index 988f3821d1..2d0c1d0563 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/message/post.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/message/post.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, channel: 'C08514ZPKB8', @@ -61,6 +60,7 @@ describe('Test SlackV2, message => post', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/message/post.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['post.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/message/search.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/message/search.test.ts index da0977dec1..bf03fff900 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/message/search.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/message/search.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, query: 'test in:test-002', @@ -205,6 +204,7 @@ describe('Test SlackV2, message => search', () => { .post('/api/search.messages?query=test%20in%3Atest-002&sort=timestamp&sort_dir=desc&count=2') .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/message/search.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['search.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/message/update.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/message/update.test.ts index b79130f93f..5b3c0254a4 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/message/update.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/message/update.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - const API_RESPONSE = { ok: true, channel: 'C08514ZPKB8', @@ -62,6 +61,7 @@ describe('Test SlackV2, message => update', () => { }) .reply(200, API_RESPONSE); - const workflows = ['nodes/Slack/test/v2/node/message/update.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['update.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/Slack/test/v2/node/user/updateProfile.test.ts b/packages/nodes-base/nodes/Slack/test/v2/node/user/updateProfile.test.ts index 54482a714b..a3234a4e62 100644 --- a/packages/nodes-base/nodes/Slack/test/v2/node/user/updateProfile.test.ts +++ b/packages/nodes-base/nodes/Slack/test/v2/node/user/updateProfile.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { testWorkflows } from '@test/nodes/Helpers'; - describe('Test SlackV2, user => updateProfile', () => { nock('https://slack.com') .post('/api/users.profile.set', { @@ -21,6 +20,7 @@ describe('Test SlackV2, user => updateProfile', () => { }) .reply(200, { profile: { test: 'OK' } }); - const workflows = ['nodes/Slack/test/v2/node/user/updateProfile.workflow.json']; - testWorkflows(workflows); + new NodeTestHarness().setupTests({ + workflowFiles: ['updateProfile.workflow.json'], + }); }); diff --git a/packages/nodes-base/nodes/SplitInBatches/test/SplitInBatches.node.test.ts b/packages/nodes-base/nodes/SplitInBatches/test/SplitInBatches.node.test.ts index 708919f602..c867b4a48d 100644 --- a/packages/nodes-base/nodes/SplitInBatches/test/SplitInBatches.node.test.ts +++ b/packages/nodes-base/nodes/SplitInBatches/test/SplitInBatches.node.test.ts @@ -1,4 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; -const workflows = getWorkflowFilenames(__dirname); +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -describe('Execute SplitInBatches Node', () => testWorkflows(workflows)); +describe('Execute SplitInBatches Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Spotify/__tests__/workflow/workflow.test.ts b/packages/nodes-base/nodes/Spotify/__tests__/workflow/workflow.test.ts index 7743b9ba35..abb3959b94 100644 --- a/packages/nodes-base/nodes/Spotify/__tests__/workflow/workflow.test.ts +++ b/packages/nodes-base/nodes/Spotify/__tests__/workflow/workflow.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { getAlbum, getAlbumTracks, @@ -24,7 +23,6 @@ describe('Spotify', () => { mock.get('/artists/12Chz98pHFMPJEknJQMWvI').reply(200, getArtist); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); }); diff --git a/packages/nodes-base/nodes/SpreadsheetFile/test/SpreadsheetFile.test.ts b/packages/nodes-base/nodes/SpreadsheetFile/test/SpreadsheetFile.test.ts index dfe7342daa..0e97cd2bae 100644 --- a/packages/nodes-base/nodes/SpreadsheetFile/test/SpreadsheetFile.test.ts +++ b/packages/nodes-base/nodes/SpreadsheetFile/test/SpreadsheetFile.test.ts @@ -1,21 +1,18 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { readFileSync } from 'fs'; -import type { IWorkflowBase, WorkflowTestData } from 'n8n-workflow'; +import type { WorkflowTestData } from 'n8n-workflow'; import path from 'path'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Execute Spreadsheet File Node', () => { + const testHarness = new NodeTestHarness(); const readBinaryFile = (fileName: string) => readFileSync(path.resolve(__dirname, fileName), 'base64'); const loadWorkflow = (fileName: string, csvName: string) => { - const workflow = Helpers.readJsonFileSync( - `nodes/SpreadsheetFile/test/${fileName}`, - ); - const node = workflow.nodes.find((n) => n.name === 'Read Binary File'); - node!.parameters.fileSelector = path.join(__dirname, csvName); - return workflow; + const workflowData = testHarness.readWorkflowJSON(fileName); + const node = workflowData.nodes.find((n) => n.name === 'Read Binary File')!; + node.parameters.fileSelector = path.join(__dirname, csvName); + return workflowData; }; const tests: WorkflowTestData[] = [ @@ -25,6 +22,7 @@ describe('Execute Spreadsheet File Node', () => { workflowData: loadWorkflow('workflow.json', 'spreadsheet.csv'), }, output: { + assertBinaryData: true, nodeData: { 'Read From File': [ [ @@ -197,18 +195,6 @@ describe('Execute Spreadsheet File Node', () => { ]; for (const testData of tests) { - // eslint-disable-next-line @typescript-eslint/no-loop-func - test(testData.description, async () => { - // execute workflow - const { result } = await executeWorkflow(testData); - - // check if result node data matches expected test data - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/Start/__tests__/StartNode.test.ts b/packages/nodes-base/nodes/Start/__tests__/StartNode.test.ts index 920b46b5ee..a89478abad 100644 --- a/packages/nodes-base/nodes/Start/__tests__/StartNode.test.ts +++ b/packages/nodes-base/nodes/Start/__tests__/StartNode.test.ts @@ -1,10 +1,8 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; -// This is (temporarily) needed to setup LoadNodesAndCredentials first -import '@test/nodes/Helpers'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; - describe('Execute Start Node', () => { + const testHarness = new NodeTestHarness(); const tests: WorkflowTestData[] = [ { description: 'should run start node', @@ -25,21 +23,13 @@ describe('Execute Start Node', () => { }, output: { nodeExecutionOrder: ['Start'], + nodeExecutionStack: [], nodeData: {}, }, }, ]; for (const testData of tests) { - test(testData.description, async () => { - // execute workflow - const { result, nodeExecutionOrder } = await executeWorkflow(testData); - // Check if the nodes did execute in the correct order - expect(nodeExecutionOrder).toEqual(testData.output.nodeExecutionOrder); - // Check if other data has correct value - expect(result.finished).toEqual(true); - expect(result.data.executionData!.contextData).toEqual({}); - expect(result.data.executionData!.nodeExecutionStack).toEqual([]); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/StopAndError/test/node/StopAndError.test.ts b/packages/nodes-base/nodes/StopAndError/test/node/StopAndError.test.ts index 4e7ce98ad1..bbd955fb09 100644 --- a/packages/nodes-base/nodes/StopAndError/test/node/StopAndError.test.ts +++ b/packages/nodes-base/nodes/StopAndError/test/node/StopAndError.test.ts @@ -1,11 +1,8 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ -import { NodeConnectionTypes, type IDataObject, type WorkflowTestData } from 'n8n-workflow'; - -// This is (temporarily) needed to setup LoadNodesAndCredentials first -import '@test/nodes/Helpers'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; +import { NodeConnectionTypes, type WorkflowTestData } from 'n8n-workflow'; describe('Execute Stop and Error Node', () => { + const testHarness = new NodeTestHarness(); const tests: WorkflowTestData[] = [ { description: 'should run stopAndError node', @@ -34,7 +31,7 @@ describe('Execute Stop and Error Node', () => { }, { parameters: { - errorMessage: 'error message from node', + errorMessage: 'error message from node 0', }, id: '196ca8fe-994d-46aa-a0ed-bd9beeaa490e', name: 'Stop and Error', @@ -65,35 +62,18 @@ describe('Execute Stop and Error Node', () => { }, }, output: { - nodeExecutionOrder: ['Start'], + nodeExecutionOrder: [ + 'When clicking "Execute Workflow"', + 'Stop and Error1', + 'Stop and Error', + ], nodeData: {}, + error: 'error message from node 0', }, }, ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - expect(result.finished).toBeUndefined(); - - const stopAndErrorRunData = result.data.resultData.runData['Stop and Error']; - const stopAndErrorMessage = ( - (stopAndErrorRunData as unknown as IDataObject[])[0].error as IDataObject - ).message; - - expect(stopAndErrorMessage).toEqual('error message from node'); - - const stopAndError1RunData = result.data.resultData.runData['Stop and Error1']; - const stopAndError1Object = ( - (stopAndError1RunData as unknown as IDataObject[])[0].error as IDataObject - ).errorResponse; - - expect(stopAndError1Object).toEqual({ - code: 404, - message: 'error object from node', - name: 'User-thrown error', - }); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/Switch/V1/test/switch.node.test.ts b/packages/nodes-base/nodes/Switch/V1/test/switch.node.test.ts index ab506aa481..c28bc0e906 100644 --- a/packages/nodes-base/nodes/Switch/V1/test/switch.node.test.ts +++ b/packages/nodes-base/nodes/Switch/V1/test/switch.node.test.ts @@ -1,4 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; -const workflows = getWorkflowFilenames(__dirname); +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -describe('Execute Switch Node', () => testWorkflows(workflows)); +describe('Execute Switch Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Switch/V2/test/switch.node.test.ts b/packages/nodes-base/nodes/Switch/V2/test/switch.node.test.ts index ab506aa481..c28bc0e906 100644 --- a/packages/nodes-base/nodes/Switch/V2/test/switch.node.test.ts +++ b/packages/nodes-base/nodes/Switch/V2/test/switch.node.test.ts @@ -1,4 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; -const workflows = getWorkflowFilenames(__dirname); +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -describe('Execute Switch Node', () => testWorkflows(workflows)); +describe('Execute Switch Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Switch/V3/test/switch.node.test.ts b/packages/nodes-base/nodes/Switch/V3/test/switch.node.test.ts index ab506aa481..c28bc0e906 100644 --- a/packages/nodes-base/nodes/Switch/V3/test/switch.node.test.ts +++ b/packages/nodes-base/nodes/Switch/V3/test/switch.node.test.ts @@ -1,4 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; -const workflows = getWorkflowFilenames(__dirname); +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -describe('Execute Switch Node', () => testWorkflows(workflows)); +describe('Execute Switch Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Telegram/tests/Workflow/workflow.test.ts b/packages/nodes-base/nodes/Telegram/tests/Workflow/workflow.test.ts index 398938346c..6763c44430 100644 --- a/packages/nodes-base/nodes/Telegram/tests/Workflow/workflow.test.ts +++ b/packages/nodes-base/nodes/Telegram/tests/Workflow/workflow.test.ts @@ -1,7 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { getChatResponse, sendMediaGroupResponse, @@ -47,7 +46,6 @@ describe('Telegram', () => { mock.post('/bottestToken/getChatMember').reply(200, getMemberResponse); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); }); diff --git a/packages/nodes-base/nodes/Totp/test/Totp.node.test.ts b/packages/nodes-base/nodes/Totp/test/Totp.node.test.ts index ae76a86934..5b41f70e9e 100644 --- a/packages/nodes-base/nodes/Totp/test/Totp.node.test.ts +++ b/packages/nodes-base/nodes/Totp/test/Totp.node.test.ts @@ -1,8 +1,6 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - jest.mock('otpauth', () => { return { TOTP: jest.fn().mockImplementation(() => { @@ -14,15 +12,17 @@ jest.mock('otpauth', () => { }); describe('Execute TOTP node', () => { + const testHarness = new NodeTestHarness(); const tests: WorkflowTestData[] = [ { description: 'Generate TOTP Token', input: { - workflowData: Helpers.readJsonFileSync('nodes/Totp/test/Totp.workflow.test.json'), + workflowData: testHarness.readWorkflowJSON('Totp.workflow.test.json'), }, output: { nodeData: { - TOTP: [[{ json: { token: '123456' } }]], // ignore secondsRemaining to prevent flakiness + // ignore json.secondsRemaining to prevent flakiness + TOTP: [[{ json: expect.objectContaining({ token: '123456' }) }]], }, }, credentials: { @@ -35,18 +35,6 @@ describe('Execute TOTP node', () => { ]; for (const testData of tests) { - // eslint-disable-next-line @typescript-eslint/no-loop-func - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - Helpers.getResultNodeData(result, testData).forEach(({ nodeName, resultData }) => { - const expected = testData.output.nodeData[nodeName][0][0].json; - const actual = resultData[0]?.[0].json; - - expect(actual?.token).toEqual(expected.token); - }); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/Transform/Aggregate/test/Aggregate.test.ts b/packages/nodes-base/nodes/Transform/Aggregate/test/Aggregate.test.ts index 9682e72a11..dee379a4dd 100644 --- a/packages/nodes-base/nodes/Transform/Aggregate/test/Aggregate.test.ts +++ b/packages/nodes-base/nodes/Transform/Aggregate/test/Aggregate.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Aggregate Node', () => testWorkflows(workflows)); +describe('Test Aggregate Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Transform/Limit/test/Limit.test.ts b/packages/nodes-base/nodes/Transform/Limit/test/Limit.test.ts index 1b9feb88cb..ecf3562d27 100644 --- a/packages/nodes-base/nodes/Transform/Limit/test/Limit.test.ts +++ b/packages/nodes-base/nodes/Transform/Limit/test/Limit.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Limit Node', () => testWorkflows(workflows)); +describe('Test Limit Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Transform/RemoveDuplicates/test/RemoveDuplicates.test.ts b/packages/nodes-base/nodes/Transform/RemoveDuplicates/test/RemoveDuplicates.test.ts index e063c46926..ae8d55f71a 100644 --- a/packages/nodes-base/nodes/Transform/RemoveDuplicates/test/RemoveDuplicates.test.ts +++ b/packages/nodes-base/nodes/Transform/RemoveDuplicates/test/RemoveDuplicates.test.ts @@ -1,12 +1,11 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { INode } from 'n8n-workflow'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { validateInputData } from '../utils'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Remove Duplicates Node', () => testWorkflows(workflows)); +describe('Test Remove Duplicates Node', () => { + new NodeTestHarness().setupTests(); +}); describe('Test Remove Duplicates Node, validateInputData util', () => { test('Should throw error for version 1', () => { @@ -28,6 +27,7 @@ describe('Test Remove Duplicates Node, validateInputData util', () => { ), ).toThrow("'country' isn't always the same type"); }); + test('Should ignore null values and not throw error for version grater than 1', () => { expect(() => validateInputData( @@ -47,6 +47,7 @@ describe('Test Remove Duplicates Node, validateInputData util', () => { ), ).not.toThrow(); }); + test('Should throw error for different types, version grater than 1', () => { expect(() => validateInputData( diff --git a/packages/nodes-base/nodes/Transform/Sort/test/Sort.test.ts b/packages/nodes-base/nodes/Transform/Sort/test/Sort.test.ts index fdbe316072..a1cab361ed 100644 --- a/packages/nodes-base/nodes/Transform/Sort/test/Sort.test.ts +++ b/packages/nodes-base/nodes/Transform/Sort/test/Sort.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Sort Node', () => testWorkflows(workflows)); +describe('Test Sort Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Transform/SplitOut/test/SplitOut.test.ts b/packages/nodes-base/nodes/Transform/SplitOut/test/SplitOut.test.ts index 24c642cfeb..82151789bb 100644 --- a/packages/nodes-base/nodes/Transform/SplitOut/test/SplitOut.test.ts +++ b/packages/nodes-base/nodes/Transform/SplitOut/test/SplitOut.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Split Out Node', () => testWorkflows(workflows)); +describe('Test Split Out Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Transform/Summarize/test/Summarize.test.ts b/packages/nodes-base/nodes/Transform/Summarize/test/Summarize.test.ts index c846b0c33c..84e9c5ab78 100644 --- a/packages/nodes-base/nodes/Transform/Summarize/test/Summarize.test.ts +++ b/packages/nodes-base/nodes/Transform/Summarize/test/Summarize.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test Summarize Node', () => testWorkflows(workflows)); +describe('Test Summarize Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts b/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts index 48c344590b..fb0953ec61 100644 --- a/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts +++ b/packages/nodes-base/nodes/Twitter/test/Twitter.test.ts @@ -1,8 +1,7 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { INodeParameterResourceLocator } from 'n8n-workflow'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { returnId } from '../V2/GenericFunctions'; const searchResult = { @@ -91,8 +90,7 @@ describe('Test Twitter Request Node', () => { .reply(200, searchResult); }); - const workflows = getWorkflowFilenames(__dirname); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); describe('X / Twitter Node unit tests', () => { diff --git a/packages/nodes-base/nodes/Wait/test/Wait.node.test.ts b/packages/nodes-base/nodes/Wait/test/Wait.node.test.ts index 9d6ad0197d..ee7e15d94f 100644 --- a/packages/nodes-base/nodes/Wait/test/Wait.node.test.ts +++ b/packages/nodes-base/nodes/Wait/test/Wait.node.test.ts @@ -1,13 +1,10 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import { mock } from 'jest-mock-extended'; import { DateTime } from 'luxon'; import { NodeOperationError, type IExecuteFunctions } from 'n8n-workflow'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { Wait } from '../Wait.node'; -const workflows = getWorkflowFilenames(__dirname); - describe('Execute Wait Node', () => { let timer: NodeJS.Timer; const { clearInterval, setInterval } = global; @@ -70,5 +67,5 @@ describe('Execute Wait Node', () => { }, ); - testWorkflows(workflows); + new NodeTestHarness().setupTests(); }); diff --git a/packages/nodes-base/nodes/Webhook/test/Webhook.test.ts b/packages/nodes-base/nodes/Webhook/test/Webhook.test.ts index 250ad3af8a..483e3077f4 100644 --- a/packages/nodes-base/nodes/Webhook/test/Webhook.test.ts +++ b/packages/nodes-base/nodes/Webhook/test/Webhook.test.ts @@ -1,15 +1,12 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { Request } from 'express'; import { mock } from 'jest-mock-extended'; import type { IWebhookFunctions } from 'n8n-workflow'; -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; - import { Webhook } from '../Webhook.node'; -const workflows = getWorkflowFilenames(__dirname); - describe('Test Webhook Node', () => { - testWorkflows(workflows); + new NodeTestHarness().setupTests(); describe('handleFormData', () => { const node = new Webhook(); diff --git a/packages/nodes-base/nodes/Wordpress/__tests__/workflow/page/page.test.ts b/packages/nodes-base/nodes/Wordpress/__tests__/workflow/page/page.test.ts index 6d3e5cdc50..d8e1f01d89 100644 --- a/packages/nodes-base/nodes/Wordpress/__tests__/workflow/page/page.test.ts +++ b/packages/nodes-base/nodes/Wordpress/__tests__/workflow/page/page.test.ts @@ -1,13 +1,10 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { pageCreate, pageGet, pageGetMany, pageUpdate } from '../apiResponses'; import { credentials } from '../credentials'; describe('Wordpress > Page Workflows', () => { - const workflows = getWorkflowFilenames(__dirname); - beforeAll(() => { const mock = nock(credentials.wordpressApi.url); mock @@ -32,5 +29,5 @@ describe('Wordpress > Page Workflows', () => { .reply(200, pageUpdate); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); diff --git a/packages/nodes-base/nodes/Wordpress/__tests__/workflow/post/post.test.ts b/packages/nodes-base/nodes/Wordpress/__tests__/workflow/post/post.test.ts index 572b42868e..f17b929f07 100644 --- a/packages/nodes-base/nodes/Wordpress/__tests__/workflow/post/post.test.ts +++ b/packages/nodes-base/nodes/Wordpress/__tests__/workflow/post/post.test.ts @@ -1,13 +1,10 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { postCreate, postGet, postGetMany, postUpdate } from '../apiResponses'; import { credentials } from '../credentials'; describe('Wordpress > Post Workflows', () => { - const workflows = getWorkflowFilenames(__dirname); - beforeAll(() => { const mock = nock(credentials.wordpressApi.url); mock.get('/wp-json/wp/v2/posts/1').reply(200, postGet); @@ -36,5 +33,5 @@ describe('Wordpress > Post Workflows', () => { .reply(200, postUpdate); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); diff --git a/packages/nodes-base/nodes/Wordpress/__tests__/workflow/user/user.test.ts b/packages/nodes-base/nodes/Wordpress/__tests__/workflow/user/user.test.ts index d90fc74892..db263cd731 100644 --- a/packages/nodes-base/nodes/Wordpress/__tests__/workflow/user/user.test.ts +++ b/packages/nodes-base/nodes/Wordpress/__tests__/workflow/user/user.test.ts @@ -1,13 +1,10 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; -import { getWorkflowFilenames, testWorkflows } from '@test/nodes/Helpers'; - import { userCreate, userGet, userGetMany, userUpdate } from '../apiResponses'; import { credentials } from '../credentials'; describe('Wordpress > User Workflows', () => { - const workflows = getWorkflowFilenames(__dirname); - beforeAll(() => { const mock = nock(credentials.wordpressApi.url); mock @@ -33,5 +30,5 @@ describe('Wordpress > User Workflows', () => { .reply(200, userUpdate); }); - testWorkflows(workflows, credentials); + new NodeTestHarness().setupTests({ credentials }); }); diff --git a/packages/nodes-base/nodes/WriteBinaryFile/test/WriteBinaryFile.test.ts b/packages/nodes-base/nodes/WriteBinaryFile/test/WriteBinaryFile.test.ts index 0db8a1e9ff..7b93a09d88 100644 --- a/packages/nodes-base/nodes/WriteBinaryFile/test/WriteBinaryFile.test.ts +++ b/packages/nodes-base/nodes/WriteBinaryFile/test/WriteBinaryFile.test.ts @@ -1,29 +1,25 @@ -/* eslint-disable @typescript-eslint/no-loop-func */ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import type { WorkflowTestData } from 'n8n-workflow'; import path from 'path'; -import { executeWorkflow } from '@test/nodes/ExecuteWorkflow'; -import * as Helpers from '@test/nodes/Helpers'; - describe('Test Write Binary File Node', () => { - const temporaryDir = Helpers.createTemporaryDir(); - const workflow = Helpers.readJsonFileSync( - 'nodes/WriteBinaryFile/test/WriteBinaryFile.workflow.json', - ); - const readFileNode = workflow.nodes.find((n: any) => n.name === 'Read Binary File'); + const testHarness = new NodeTestHarness(); + const workflowData = testHarness.readWorkflowJSON('WriteBinaryFile.workflow.json'); + const readFileNode = workflowData.nodes.find((n) => n.name === 'Read Binary File')!; readFileNode.parameters.filePath = path.join(__dirname, 'image.jpg'); - const writeFileNode = workflow.nodes.find((n: any) => n.name === 'Write Binary File'); - const writeFilePath = path.join(temporaryDir, 'image-written.jpg'); + const writeFileNode = workflowData.nodes.find((n) => n.name === 'Write Binary File')!; + const writeFilePath = path.join(testHarness.temporaryDir, 'image-written.jpg'); writeFileNode.parameters.fileName = writeFilePath; const tests: WorkflowTestData[] = [ { description: 'nodes/WriteBinaryFile/test/WriteBinaryFile.workflow.json', input: { - workflowData: workflow, + workflowData, }, output: { + assertBinaryData: true, nodeData: { 'Write Binary File': [ [ @@ -37,7 +33,6 @@ describe('Test Write Binary File Node', () => { fileType: 'image', fileExtension: 'jpg', data: '/9j/4AAQSkZJRgABAQEASABIAAD/4QBmRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAAQAAAATgAAAAAAARlJAAAD6AABGUkAAAPocGFpbnQubmV0IDUuMC4xAP/bAEMAIBYYHBgUIBwaHCQiICYwUDQwLCwwYkZKOlB0Znp4cmZwboCQuJyAiK6KbnCg2qKuvsTO0M58muLy4MjwuMrOxv/bAEMBIiQkMCowXjQ0XsaEcITGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxv/AABEIAB8AOwMBEgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOgqgrXF2zNHJ5aKcD3oNPZ23di/VKG82bkuTh1OMgdaAdOSLtZ6G5ut0iSeWoOAKAdO27NCqUN8oQrcHDqccDrQDpyRNPdRwEKcsx7CobIebPLORwThc0inGMF724jagNpxG4OOM1dIDAgjIPBpkqUOxnR2pmh85pW3nJB9KkNi4yqTssZ6rSNXNX0ehHFfusYDLuI7+tXY4I40ChQcdzQRKcL7Fb7PcQO32cqUY5we1XqZPtH11KsFoFDGYK7sckkZxVqgTnJlEQXMBZYGUoTkZ7VeoH7RvcqwWaIh80K7k5JIq1QJzkyhbMtvdSxMdqnlc1amgjmx5i5I70inNSVpFdrmaWRltkBVerHvUW57B2AUNGxyOaC+VW9xXLVrcGbcjrtkXqKZZxvveeTAL9APSgiooq1ty3RTMj//2Q==', - directory: __dirname, fileName: 'image.jpg', fileSize: '1.04 kB', }, @@ -51,15 +46,6 @@ describe('Test Write Binary File Node', () => { ]; for (const testData of tests) { - test(testData.description, async () => { - const { result } = await executeWorkflow(testData); - - const resultNodeData = Helpers.getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => - expect(resultData).toEqual(testData.output.nodeData[nodeName]), - ); - - expect(result.finished).toEqual(true); - }); + testHarness.setupTest(testData); } }); diff --git a/packages/nodes-base/nodes/Xml/test/node/Xml.test.ts b/packages/nodes-base/nodes/Xml/test/node/Xml.test.ts index 3be88943f2..52a6f9aeef 100644 --- a/packages/nodes-base/nodes/Xml/test/node/Xml.test.ts +++ b/packages/nodes-base/nodes/Xml/test/node/Xml.test.ts @@ -1,5 +1,5 @@ -import { testWorkflows, getWorkflowFilenames } from '@test/nodes/Helpers'; +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; -const workflows = getWorkflowFilenames(__dirname); - -describe('Test XML Node', () => testWorkflows(workflows)); +describe('Test XML Node', () => { + new NodeTestHarness().setupTests(); +}); diff --git a/packages/nodes-base/test/nodes/ExecuteWorkflow.ts b/packages/nodes-base/test/nodes/ExecuteWorkflow.ts deleted file mode 100644 index 83b6d41423..0000000000 --- a/packages/nodes-base/test/nodes/ExecuteWorkflow.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Container } from '@n8n/di'; -import { mock } from 'jest-mock-extended'; -import { ExecutionLifecycleHooks, WorkflowExecute } from 'n8n-core'; -import type { - IRun, - IRunExecutionData, - IWorkflowExecuteAdditionalData, - WorkflowTestData, -} from 'n8n-workflow'; -import { createDeferredPromise, Workflow } from 'n8n-workflow'; -import nock from 'nock'; - -import { CredentialsHelper } from './credentials-helper'; -import { NodeTypes } from './node-types'; - -export async function executeWorkflow(testData: WorkflowTestData) { - const nodeTypes = Container.get(NodeTypes); - - const credentialsHelper = Container.get(CredentialsHelper); - credentialsHelper.setCredentials(testData.credentials ?? {}); - - if (testData.nock) { - const { baseUrl, mocks } = testData.nock; - const agent = nock(baseUrl); - mocks.forEach( - ({ - method, - path, - statusCode, - requestBody, - requestHeaders, - responseBody, - responseHeaders, - }) => { - let mock = agent[method](path, requestBody); - - // nock interceptor reqheaders option is ignored, so we chain matchHeader() - // agent[method](path, requestBody, { reqheaders: requestHeaders }).reply(statusCode, responseBody, responseHeaders) - // https://github.com/nock/nock/issues/2545 - if (requestHeaders && Object.keys(requestHeaders).length > 0) { - Object.entries(requestHeaders).forEach(([key, value]) => { - mock = mock.matchHeader(key, value); - }); - } - - mock.reply(statusCode, responseBody, responseHeaders); - }, - ); - } - - const executionMode = testData.trigger?.mode ?? 'manual'; - const workflowInstance = new Workflow({ - id: 'test', - nodes: testData.input.workflowData.nodes, - connections: testData.input.workflowData.connections, - active: false, - nodeTypes, - settings: testData.input.workflowData.settings, - }); - const waitPromise = createDeferredPromise(); - const nodeExecutionOrder: string[] = []; - - const hooks = new ExecutionLifecycleHooks('trigger', '1', mock()); - hooks.addHandler('nodeExecuteAfter', (nodeName) => { - nodeExecutionOrder.push(nodeName); - }); - hooks.addHandler('workflowExecuteAfter', (fullRunData) => waitPromise.resolve(fullRunData)); - - const additionalData = mock({ - hooks, - // Get from node.parameters - currentNodeParameters: undefined, - }); - additionalData.credentialsHelper = credentialsHelper; - - let executionData: IRun; - const runExecutionData: IRunExecutionData = { - resultData: { - runData: {}, - }, - executionData: { - metadata: {}, - contextData: {}, - waitingExecution: {}, - waitingExecutionSource: null, - nodeExecutionStack: [ - { - node: workflowInstance.getStartNode()!, - data: { - main: [[testData.trigger?.input ?? { json: {} }]], - }, - source: null, - }, - ], - }, - }; - const workflowExecute = new WorkflowExecute(additionalData, executionMode, runExecutionData); - executionData = await workflowExecute.processRunExecutionData(workflowInstance); - - const result = await waitPromise.promise; - return { executionData, result, nodeExecutionOrder }; -} diff --git a/packages/nodes-base/test/nodes/Helpers.ts b/packages/nodes-base/test/nodes/Helpers.ts index e927ac0284..aa1b73a4d4 100644 --- a/packages/nodes-base/test/nodes/Helpers.ts +++ b/packages/nodes-base/test/nodes/Helpers.ts @@ -1,188 +1,13 @@ -import { Container } from '@n8n/di'; -import { readFileSync, readdirSync, mkdtempSync } from 'fs'; import { get } from 'lodash'; -import { isEmpty } from 'lodash'; import { constructExecutionMetaData } from 'n8n-core'; -import type { - ICredentialDataDecryptedObject, - IDataObject, - IExecuteFunctions, - IGetNodeParameterOptions, - INode, - IRun, - IWorkflowBase, - WorkflowTestData, -} from 'n8n-workflow'; -import { ApplicationError } from 'n8n-workflow'; -import nock from 'nock'; -import { tmpdir } from 'os'; -import path from 'path'; - -import { executeWorkflow } from './ExecuteWorkflow'; -import { LoadNodesAndCredentials } from './load-nodes-and-credentials'; - -const baseDir = path.resolve(__dirname, '../..'); - -export const readJsonFileSync = (filePath: string) => - JSON.parse(readFileSync(path.join(baseDir, filePath), 'utf-8')) as T; - -const loadNodesAndCredentials = new LoadNodesAndCredentials(baseDir); -Container.set(LoadNodesAndCredentials, loadNodesAndCredentials); - -beforeAll(async () => await loadNodesAndCredentials.init()); -beforeEach(() => nock.disableNetConnect()); - -export function createTemporaryDir(prefix = 'n8n') { - return mkdtempSync(path.join(tmpdir(), prefix)); -} - -export function getResultNodeData(result: IRun, testData: WorkflowTestData) { - return Object.keys(testData.output.nodeData).map((nodeName) => { - const error = result.data.resultData.error; - // If there was an error running the workflow throw it for easier debugging - // and to surface all issues - if (error?.cause) throw error.cause; - if (error) throw error; - - if (result.data.resultData.runData[nodeName] === undefined) { - // log errors from other nodes - Object.keys(result.data.resultData.runData).forEach((key) => { - const error = result.data.resultData.runData[key][0]?.error; - if (error) { - console.log(`Node ${key}\n`, error); - } - }); - - throw new ApplicationError(`Data for node "${nodeName}" is missing!`, { level: 'warning' }); - } - const resultData = result.data.resultData.runData[nodeName].map((nodeData) => { - if (nodeData.data === undefined) { - return null; - } - return nodeData.data.main[0]!.map((entry) => { - if (entry.binary && isEmpty(entry.binary)) delete entry.binary; - delete entry.pairedItem; - return entry; - }); - }); - return { - nodeName, - resultData, - }; - }); -} - -export const equalityTest = async (testData: WorkflowTestData) => { - // execute workflow - const { result } = await executeWorkflow(testData); - - // check if result node data matches expected test data - const resultNodeData = getResultNodeData(result, testData); - resultNodeData.forEach(({ nodeName, resultData }) => { - const msg = `Equality failed for "${testData.description}" at node "${nodeName}"`; - resultData.forEach((item) => { - item?.forEach(({ binary, json }) => { - if (binary) { - // @ts-ignore - delete binary.data.data; - delete binary.data.directory; - } - - // Convert errors to JSON so tests can compare - if (json?.error instanceof Error) { - json.error = JSON.parse( - JSON.stringify(json.error, ['message', 'name', 'description', 'context']), - ); - } - }); - }); - return expect(resultData, msg).toEqual(testData.output.nodeData[nodeName]); - }); - - expect(result.finished || result.status === 'waiting').toEqual(true); -}; - -const preparePinData = (pinData: IDataObject) => { - const returnData = Object.keys(pinData).reduce( - (acc, key) => { - const data = pinData[key] as IDataObject[]; - acc[key] = [data]; - return acc; - }, - {} as { - [key: string]: IDataObject[][]; - }, - ); - return returnData; -}; - -export const workflowToTests = ( - workflowFiles: string[], - credentials?: Record, -) => { - const testCases: WorkflowTestData[] = []; - for (const filePath of workflowFiles) { - const description = filePath.replace('.json', ''); - const workflowData = readJsonFileSync>( - filePath, - ); - const testDir = path.join(baseDir, path.dirname(filePath)); - workflowData.nodes.forEach((node) => { - if (node.parameters) { - node.parameters = JSON.parse( - JSON.stringify(node.parameters).replace(/"C:\\\\Test\\\\(.*)"/, `"${testDir}/$1"`), - ); - } - }); - if (workflowData.pinData === undefined) { - throw new ApplicationError('Workflow data does not contain pinData', { level: 'warning' }); - } - - const nodeData = preparePinData(workflowData.pinData); - delete workflowData.pinData; - - const { trigger } = workflowData; - delete workflowData.trigger; - - const input = { workflowData }; - const output = { nodeData }; - - testCases.push({ description, input, output, trigger, credentials }); - } - return testCases; -}; - -export const testWorkflows = ( - workflows: string[], - credentials?: Record, -) => { - const tests = workflowToTests(workflows, credentials); - - for (const testData of tests) { - test(testData.description, async () => await equalityTest(testData)); - } -}; - -export const getWorkflowFilenames = (dirname: string) => { - const workflows: string[] = []; - - const filenames = readdirSync(dirname); - const testFolder = dirname.split(`${path.sep}nodes-base${path.sep}`)[1]; - filenames.forEach((file) => { - if (file.endsWith('.json')) { - workflows.push(path.join(testFolder, file)); - } - }); - - return workflows; -}; +import type { IDataObject, IExecuteFunctions, IGetNodeParameterOptions, INode } from 'n8n-workflow'; export const createMockExecuteFunction = ( nodeParameters: IDataObject, nodeMock: INode, continueBool = false, -) => { - const fakeExecuteFunction = { +) => + ({ getNodeParameter( parameterName: string, _itemIndex: number, @@ -201,6 +26,4 @@ export const createMockExecuteFunction = ( helpers: { constructExecutionMetaData, }, - } as unknown as T; - return fakeExecuteFunction; -}; + }) as unknown as T; diff --git a/packages/nodes-base/test/nodes/load-nodes-and-credentials.ts b/packages/nodes-base/test/nodes/load-nodes-and-credentials.ts deleted file mode 100644 index 8ee1b05407..0000000000 --- a/packages/nodes-base/test/nodes/load-nodes-and-credentials.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Service } from '@n8n/di'; -import { LazyPackageDirectoryLoader } from 'n8n-core'; -import type { - ICredentialType, - INodeType, - IVersionedNodeType, - KnownNodesAndCredentials, - LoadedClass, - LoadingDetails, -} from 'n8n-workflow'; - -/** This rewrites the nodes/credentials source path to load the typescript code instead of the compiled javascript code */ -const fixSourcePath = (loadInfo: LoadingDetails) => { - if (!loadInfo) return; - loadInfo.sourcePath = loadInfo.sourcePath.replace(/^dist\//, './').replace(/\.js$/, '.ts'); -}; - -@Service() -export class LoadNodesAndCredentials { - private loader: LazyPackageDirectoryLoader; - - readonly known: KnownNodesAndCredentials = { nodes: {}, credentials: {} }; - - constructor(baseDir: string) { - this.loader = new LazyPackageDirectoryLoader(baseDir); - } - - async init() { - await this.loader.loadAll(); - this.known.credentials = this.loader.known.credentials; - this.known.nodes = this.loader.known.nodes; - } - - recognizesCredential(credentialType: string): boolean { - return credentialType in this.known.credentials; - } - - getCredential(credentialType: string): LoadedClass { - fixSourcePath(this.known.credentials[credentialType]); - return this.loader.getCredential(credentialType); - } - - getNode(fullNodeType: string): LoadedClass { - const nodeType = fullNodeType.split('.')[1]; - fixSourcePath(this.known.nodes[nodeType]); - return this.loader.getNode(nodeType); - } -} diff --git a/packages/nodes-base/tsconfig.json b/packages/nodes-base/tsconfig.json index 81c91734b8..96625431c9 100644 --- a/packages/nodes-base/tsconfig.json +++ b/packages/nodes-base/tsconfig.json @@ -7,7 +7,8 @@ "paths": { "@credentials/*": ["./credentials/*"], "@test/*": ["./test/*"], - "@utils/*": ["./utils/*"] + "@utils/*": ["./utils/*"], + "@nodes-testing/*": ["../core/nodes-testing/*"] }, "tsBuildInfoFile": "dist/typecheck.tsbuildinfo", "emitDecoratorMetadata": true, diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index bbd8c1fddd..73d6b97b8b 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -2436,11 +2436,14 @@ export interface WorkflowTestData { }; }; output: { + assertBinaryData?: boolean; nodeExecutionOrder?: string[]; + nodeExecutionStack?: IExecuteData[]; testAllOutputs?: boolean; nodeData: { [key: string]: any[][]; }; + error?: string; }; nock?: { baseUrl: string;