mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
fix(Mandrill Node): Fix a typo in subaccount in options (#18103)
This commit is contained in:
@@ -766,8 +766,8 @@ export class Mandrill implements INodeType {
|
|||||||
message.from_name = options.fromName;
|
message.from_name = options.fromName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.subaccount) {
|
if (options.subAccount) {
|
||||||
message.subaccount = options.subaccount;
|
message.subaccount = options.subAccount.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const body: Body = {
|
const body: Body = {
|
||||||
|
|||||||
143
packages/nodes-base/nodes/Mandrill/test/GenericFunctions.test.ts
Normal file
143
packages/nodes-base/nodes/Mandrill/test/GenericFunctions.test.ts
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import {
|
||||||
|
getGoogleAnalyticsDomainsArray,
|
||||||
|
getTags,
|
||||||
|
getToEmailArray,
|
||||||
|
validateJSON,
|
||||||
|
} from '../GenericFunctions';
|
||||||
|
|
||||||
|
describe('Mandrill GenericFunctions', () => {
|
||||||
|
describe('getToEmailArray', () => {
|
||||||
|
it('should convert single email to array', () => {
|
||||||
|
const result = getToEmailArray('test@example.com');
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
email: 'test@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert comma-separated emails to array', () => {
|
||||||
|
const result = getToEmailArray('test1@example.com,test2@example.com,test3@example.com');
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
email: 'test1@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email: 'test2@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email: 'test3@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle emails with spaces after commas', () => {
|
||||||
|
const result = getToEmailArray('test1@example.com, test2@example.com, test3@example.com');
|
||||||
|
expect(result).toEqual([
|
||||||
|
{
|
||||||
|
email: 'test1@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email: ' test2@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
email: ' test3@example.com',
|
||||||
|
type: 'to',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getGoogleAnalyticsDomainsArray', () => {
|
||||||
|
it('should convert single domain to array', () => {
|
||||||
|
const result = getGoogleAnalyticsDomainsArray('example.com');
|
||||||
|
expect(result).toEqual(['example.com']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert comma-separated domains to array', () => {
|
||||||
|
const result = getGoogleAnalyticsDomainsArray('example.com,test.com,demo.org');
|
||||||
|
expect(result).toEqual(['example.com', 'test.com', 'demo.org']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle domains with spaces after commas', () => {
|
||||||
|
const result = getGoogleAnalyticsDomainsArray('example.com, test.com, demo.org');
|
||||||
|
expect(result).toEqual(['example.com', ' test.com', ' demo.org']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty string', () => {
|
||||||
|
const result = getGoogleAnalyticsDomainsArray('');
|
||||||
|
expect(result).toEqual(['']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getTags', () => {
|
||||||
|
it('should convert single tag to array', () => {
|
||||||
|
const result = getTags('newsletter');
|
||||||
|
expect(result).toEqual(['newsletter']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert comma-separated tags to array', () => {
|
||||||
|
const result = getTags('newsletter,marketing,promotion');
|
||||||
|
expect(result).toEqual(['newsletter', 'marketing', 'promotion']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle tags with spaces after commas', () => {
|
||||||
|
const result = getTags('newsletter, marketing, promotion');
|
||||||
|
expect(result).toEqual(['newsletter', ' marketing', ' promotion']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty string', () => {
|
||||||
|
const result = getTags('');
|
||||||
|
expect(result).toEqual(['']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateJSON', () => {
|
||||||
|
it('should parse valid JSON object', () => {
|
||||||
|
const result = validateJSON('{"Test": "value", "number": 123}');
|
||||||
|
expect(result).toEqual({ Test: 'value', number: 123 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse valid JSON array', () => {
|
||||||
|
const result = validateJSON('[{"name": "Test", "value": "data"}]');
|
||||||
|
expect(result).toEqual([{ name: 'Test', value: 'data' }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty array for invalid JSON', () => {
|
||||||
|
const result = validateJSON('invalid json');
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return empty array for undefined input', () => {
|
||||||
|
const result = validateJSON(undefined);
|
||||||
|
expect(result).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null for null JSON string', () => {
|
||||||
|
const result = validateJSON('null');
|
||||||
|
expect(result).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse nested JSON correctly', () => {
|
||||||
|
const result = validateJSON('{"metadata": {"key": "value"}, "array": [1, 2, 3]}');
|
||||||
|
expect(result).toEqual({
|
||||||
|
metadata: { key: 'value' },
|
||||||
|
array: [1, 2, 3],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle JSON with special characters', () => {
|
||||||
|
const result = validateJSON('{"message": "Hello\\nWorld\\t!", "emoji": "🎉"}');
|
||||||
|
expect(result).toEqual({
|
||||||
|
message: 'Hello\nWorld\t!',
|
||||||
|
emoji: '🎉',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
101
packages/nodes-base/nodes/Mandrill/test/Mandrill.node.test.ts
Normal file
101
packages/nodes-base/nodes/Mandrill/test/Mandrill.node.test.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||||
|
import { mock, mockDeep } from 'jest-mock-extended';
|
||||||
|
import type { ILoadOptionsFunctions, INode } from 'n8n-workflow';
|
||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
|
import { Mandrill } from '../Mandrill.node';
|
||||||
|
|
||||||
|
describe('Test Mandrill Node', () => {
|
||||||
|
describe('Messages', () => {
|
||||||
|
const mandrillNock = nock('https://mandrillapp.com/api/1.0');
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
// Mock sendTemplate API call with subaccount verification
|
||||||
|
mandrillNock
|
||||||
|
.post('/messages/send-template.json', (body) => {
|
||||||
|
// Verify that subaccount is properly passed to the API
|
||||||
|
return (
|
||||||
|
body.message &&
|
||||||
|
body.message.subaccount === 'test-subaccount' &&
|
||||||
|
body.template_name === 'test-template'
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.reply(200, [
|
||||||
|
{
|
||||||
|
email: 'recipient@example.com',
|
||||||
|
status: 'sent',
|
||||||
|
reject_reason: null,
|
||||||
|
_id: 'test-message-id-456',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Mock sendTemplate API call specifically for subaccount regression test
|
||||||
|
mandrillNock
|
||||||
|
.post('/messages/send-template.json', (body) => {
|
||||||
|
// Verify regression test scenario: subaccount is properly passed
|
||||||
|
return (
|
||||||
|
body.message &&
|
||||||
|
body.message.subaccount === 'regression-test-subaccount' &&
|
||||||
|
body.template_name === 'test-template-subaccount'
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.reply(200, [
|
||||||
|
{
|
||||||
|
email: 'recipient@example.com',
|
||||||
|
status: 'sent',
|
||||||
|
reject_reason: null,
|
||||||
|
_id: 'test-subaccount-message-id',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Mock sendHtml API call
|
||||||
|
mandrillNock.post('/messages/send.json').reply(200, [
|
||||||
|
{
|
||||||
|
email: 'recipient@example.com',
|
||||||
|
status: 'rejected',
|
||||||
|
_id: 'test-message-id-123',
|
||||||
|
reject_reason: 'global-block',
|
||||||
|
queued_reason: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => mandrillNock.done());
|
||||||
|
|
||||||
|
new NodeTestHarness().setupTests({
|
||||||
|
workflowFiles: [
|
||||||
|
'sendTemplate.workflow.json',
|
||||||
|
'sendTemplateWithSubaccount.workflow.json',
|
||||||
|
'sendHtml.workflow.json',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('loadOptions', () => {
|
||||||
|
describe('getTemplates', () => {
|
||||||
|
it('should return a list of Mandrill templates', async () => {
|
||||||
|
const mandrill = new Mandrill();
|
||||||
|
const loadOptionsFunctions = mockDeep<ILoadOptionsFunctions>();
|
||||||
|
loadOptionsFunctions.getNode.mockReturnValue(mock<INode>());
|
||||||
|
loadOptionsFunctions.getCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
|
||||||
|
loadOptionsFunctions.helpers.request.mockResolvedValue([
|
||||||
|
{
|
||||||
|
slug: 'template-1',
|
||||||
|
name: 'Test Template 1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'template-2',
|
||||||
|
name: 'Test Template 2',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await mandrill.methods.loadOptions.getTemplates.call(loadOptionsFunctions);
|
||||||
|
|
||||||
|
expect(result).toEqual([
|
||||||
|
{ name: 'Test Template 1', value: 'template-1' },
|
||||||
|
{ name: 'Test Template 2', value: 'template-2' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "sendHtml",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "test-trigger-node-id",
|
||||||
|
"name": "When clicking 'Execute workflow'",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"operation": "sendHtml",
|
||||||
|
"fromEmail": "sender@example.com",
|
||||||
|
"toEmail": "recipient@example.com",
|
||||||
|
"options": {
|
||||||
|
"html": "<h1>Test HTML Content</h1>",
|
||||||
|
"subject": "Test HTML Subject"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "test-mandrill-node-id",
|
||||||
|
"name": "Mandrill",
|
||||||
|
"type": "n8n-nodes-base.mandrill",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [220, 0],
|
||||||
|
"credentials": {
|
||||||
|
"mandrillApi": {
|
||||||
|
"id": "test-credentials-id",
|
||||||
|
"name": "Test Mandrill API"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking 'Execute workflow'": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Mandrill",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Mandrill": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"email": "recipient@example.com",
|
||||||
|
"status": "rejected",
|
||||||
|
"_id": "test-message-id-123",
|
||||||
|
"reject_reason": "global-block",
|
||||||
|
"queued_reason": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"active": false,
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1"
|
||||||
|
},
|
||||||
|
"versionId": "test-version-id",
|
||||||
|
"meta": {
|
||||||
|
"templateCredsSetupCompleted": true,
|
||||||
|
"instanceId": "test-instance-id"
|
||||||
|
},
|
||||||
|
"id": "test-workflow-id-2",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"name": "sendTemplate",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "test-trigger-node-id",
|
||||||
|
"name": "When clicking 'Execute workflow'",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "message",
|
||||||
|
"operation": "sendTemplate",
|
||||||
|
"template": "test-template",
|
||||||
|
"fromEmail": "sender@example.com",
|
||||||
|
"toEmail": "recipient@example.com",
|
||||||
|
"options": {
|
||||||
|
"subAccount": "test-subaccount"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "test-mandrill-node-id",
|
||||||
|
"name": "Mandrill",
|
||||||
|
"type": "n8n-nodes-base.mandrill",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [220, 0],
|
||||||
|
"credentials": {
|
||||||
|
"mandrillApi": {
|
||||||
|
"id": "test-credentials-id",
|
||||||
|
"name": "Test Mandrill API"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking 'Execute workflow'": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Mandrill",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Mandrill": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"email": "recipient@example.com",
|
||||||
|
"status": "sent",
|
||||||
|
"reject_reason": null,
|
||||||
|
"_id": "test-message-id-456"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"active": false,
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1"
|
||||||
|
},
|
||||||
|
"versionId": "test-version-id",
|
||||||
|
"meta": {
|
||||||
|
"instanceId": "test-instance"
|
||||||
|
},
|
||||||
|
"id": "test-workflow-id",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "sendTemplateWithSubaccount",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "test-trigger-node-id",
|
||||||
|
"name": "When clicking 'Execute workflow'",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"resource": "message",
|
||||||
|
"operation": "sendTemplate",
|
||||||
|
"template": "test-template-subaccount",
|
||||||
|
"fromEmail": "sender@example.com",
|
||||||
|
"toEmail": "recipient@example.com",
|
||||||
|
"options": {
|
||||||
|
"subAccount": "regression-test-subaccount",
|
||||||
|
"subject": "Testing subaccount functionality"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": "test-mandrill-node-id",
|
||||||
|
"name": "Mandrill",
|
||||||
|
"type": "n8n-nodes-base.mandrill",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [220, 0],
|
||||||
|
"credentials": {
|
||||||
|
"mandrillApi": {
|
||||||
|
"id": "test-credentials-id",
|
||||||
|
"name": "Test Mandrill API"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking 'Execute workflow'": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Mandrill",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Mandrill": [
|
||||||
|
{
|
||||||
|
"json": {
|
||||||
|
"email": "recipient@example.com",
|
||||||
|
"status": "sent",
|
||||||
|
"reject_reason": null,
|
||||||
|
"_id": "test-subaccount-message-id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"active": false,
|
||||||
|
"settings": {
|
||||||
|
"executionOrder": "v1"
|
||||||
|
},
|
||||||
|
"versionId": "test-version-id",
|
||||||
|
"meta": {
|
||||||
|
"instanceId": "test-instance"
|
||||||
|
},
|
||||||
|
"id": "test-workflow-subaccount-id",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user