first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import { mockDeep } from 'jest-mock-extended';
|
||||
import type { IExecuteFunctions } from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
|
||||
import { Xml } from '../../Xml.node';
|
||||
|
||||
describe('Test XML Node', () => {
|
||||
new NodeTestHarness().setupTests();
|
||||
});
|
||||
|
||||
describe('Xml Node - options validation', () => {
|
||||
const FORBIDDEN_KEYS = ['__proto__', 'constructor', 'prototype'];
|
||||
|
||||
let xmlNode: Xml;
|
||||
let mockExecuteFunctions: ReturnType<typeof mockDeep<IExecuteFunctions>>;
|
||||
|
||||
beforeEach(() => {
|
||||
xmlNode = new Xml();
|
||||
mockExecuteFunctions = mockDeep<IExecuteFunctions>();
|
||||
mockExecuteFunctions.getNode.mockReturnValue({
|
||||
id: 'xml-node',
|
||||
name: 'XML',
|
||||
type: 'n8n-nodes-base.xml',
|
||||
typeVersion: 1,
|
||||
position: [0, 0],
|
||||
parameters: {},
|
||||
});
|
||||
mockExecuteFunctions.getInputData.mockReturnValue([
|
||||
{ json: { data: '<root foo="bar">x</root>' } },
|
||||
]);
|
||||
});
|
||||
|
||||
const setupGetNodeParameter = (mode: string, options: Record<string, unknown>) => {
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(parameterName: string, _itemIndex: number, fallbackValue?: unknown) => {
|
||||
if (parameterName === 'mode') return mode;
|
||||
if (parameterName === 'dataPropertyName') return 'data';
|
||||
if (parameterName === 'options') return options;
|
||||
return fallbackValue as object;
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
describe('attrkey validation', () => {
|
||||
test.each(FORBIDDEN_KEYS)(
|
||||
'should reject invalid attrkey "%s" in xmlToJson mode',
|
||||
async (forbiddenKey) => {
|
||||
setupGetNodeParameter('xmlToJson', { attrkey: forbiddenKey, mergeAttrs: false });
|
||||
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
`The "Attribute Key" option value "${forbiddenKey}" is not allowed`,
|
||||
);
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
NodeOperationError,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.each(FORBIDDEN_KEYS)(
|
||||
'should reject invalid attrkey "%s" in jsonToxml mode',
|
||||
async (forbiddenKey) => {
|
||||
setupGetNodeParameter('jsonToxml', { attrkey: forbiddenKey });
|
||||
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
`The "Attribute Key" option value "${forbiddenKey}" is not allowed`,
|
||||
);
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
NodeOperationError,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('charkey validation', () => {
|
||||
test.each(FORBIDDEN_KEYS)(
|
||||
'should reject invalid charkey "%s" in xmlToJson mode',
|
||||
async (forbiddenKey) => {
|
||||
setupGetNodeParameter('xmlToJson', { charkey: forbiddenKey });
|
||||
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
`The "Character Key" option value "${forbiddenKey}" is not allowed`,
|
||||
);
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
NodeOperationError,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.each(FORBIDDEN_KEYS)(
|
||||
'should reject invalid charkey "%s" in jsonToxml mode',
|
||||
async (forbiddenKey) => {
|
||||
setupGetNodeParameter('jsonToxml', { charkey: forbiddenKey });
|
||||
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
`The "Character Key" option value "${forbiddenKey}" is not allowed`,
|
||||
);
|
||||
await expect(xmlNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
|
||||
NodeOperationError,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"name": "My workflow",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "7f04c09e-5a60-4a0c-a336-ef38e4732452",
|
||||
"name": "When clicking \"Execute Workflow\"",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [860, 380]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"data": [
|
||||
{
|
||||
"a": {
|
||||
"b": {
|
||||
"c": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "be80ce82-d312-460d-ac79-05c0626845ad",
|
||||
"name": "Code",
|
||||
"type": "n8n-nodes-testing.testData",
|
||||
"typeVersion": 1,
|
||||
"position": [1080, 380]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "jsonToxml",
|
||||
"options": {}
|
||||
},
|
||||
"id": "c352655b-e0dc-4f7c-a63a-ff1bc5f1909f",
|
||||
"name": "XML",
|
||||
"type": "n8n-nodes-base.xml",
|
||||
"typeVersion": 1,
|
||||
"position": [1300, 380]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"id": "21547e44-133e-4c3b-a601-0cffba1daf9b",
|
||||
"name": "XML1",
|
||||
"type": "n8n-nodes-base.xml",
|
||||
"typeVersion": 1,
|
||||
"position": [1500, 380]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"values": {
|
||||
"string": [
|
||||
{
|
||||
"name": "new",
|
||||
"value": "={{ $json.a }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "632dee22-10d1-424d-b1d2-673b95b32943",
|
||||
"name": "Set",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 2,
|
||||
"position": [1720, 380]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"Set": [
|
||||
{
|
||||
"json": {
|
||||
"a": {
|
||||
"b": {
|
||||
"c": "1"
|
||||
}
|
||||
},
|
||||
"new": {
|
||||
"b": {
|
||||
"c": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking \"Execute Workflow\"": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Code",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Code": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "XML",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"XML": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "XML1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"XML1": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Set",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {},
|
||||
"versionId": "14c1d4b8-3546-4692-8e8a-44c244c79bcc",
|
||||
"id": "0G78Fh2FTnM46kuR",
|
||||
"meta": {
|
||||
"instanceId": "021d3c82ba2d3bc090cbf4fc81c9312668bcc34297e022bb3438c5c88a43a5ff"
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"name": "xml tests",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "745d1191-f221-4eda-9d09-611233f97edd",
|
||||
"name": "When clicking \"Execute Workflow\"",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [460, 520]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "jsonToxml",
|
||||
"options": {}
|
||||
},
|
||||
"id": "fb48ca4c-5ae2-4c57-9ca9-2080d06dbf65",
|
||||
"name": "XML",
|
||||
"type": "n8n-nodes-base.xml",
|
||||
"typeVersion": 1,
|
||||
"position": [960, 280]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"data": {
|
||||
"data": {
|
||||
"id": 1,
|
||||
"firstName": "Adam",
|
||||
"secondName": "Smith",
|
||||
"fullName": "Adam Smith"
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "6a04ca32-c9cc-4cb1-a6b9-3a505b1c2dd5",
|
||||
"name": "Code",
|
||||
"type": "n8n-nodes-testing.testData",
|
||||
"typeVersion": 1,
|
||||
"position": [700, 400]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "jsonToxml",
|
||||
"options": {
|
||||
"headless": true
|
||||
}
|
||||
},
|
||||
"id": "cd740e65-5117-4bec-a3b3-6863ba25f232",
|
||||
"name": "XML1",
|
||||
"type": "n8n-nodes-base.xml",
|
||||
"typeVersion": 1,
|
||||
"position": [960, 500]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"data": {
|
||||
"data": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?> <data> <id>1</id> <firstName>Adam</firstName> <secondName>Smith</secondName> <fullName>Adam Smith</fullName> </data>"
|
||||
}
|
||||
},
|
||||
"id": "817afbf7-9342-403f-8dc0-c4a3905fde4d",
|
||||
"name": "Code1",
|
||||
"type": "n8n-nodes-testing.testData",
|
||||
"typeVersion": 1,
|
||||
"position": [680, 640]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"id": "f0f37a8f-9136-42e8-be34-f32b77e4aa88",
|
||||
"name": "XML2",
|
||||
"type": "n8n-nodes-base.xml",
|
||||
"typeVersion": 1,
|
||||
"position": [940, 700]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"XML": [
|
||||
{
|
||||
"json": {
|
||||
"data": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<data>\n <id>1</id>\n <firstName>Adam</firstName>\n <secondName>Smith</secondName>\n <fullName>Adam Smith</fullName>\n</data>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"XML1": [
|
||||
{
|
||||
"json": {
|
||||
"data": "<data>\n <id>1</id>\n <firstName>Adam</firstName>\n <secondName>Smith</secondName>\n <fullName>Adam Smith</fullName>\n</data>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"XML2": [
|
||||
{
|
||||
"json": {
|
||||
"data": {
|
||||
"id": "1",
|
||||
"firstName": "Adam",
|
||||
"secondName": "Smith",
|
||||
"fullName": "Adam Smith"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking \"Execute Workflow\"": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Code",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "Code1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Code": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "XML",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "XML1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Code1": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "XML2",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {},
|
||||
"versionId": "c1fde9d5-f27c-4e62-bc5c-8be787dcc227",
|
||||
"id": "109",
|
||||
"meta": {
|
||||
"instanceId": "36203ea1ce3cef713fa25999bd9874ae26b9e4c2c3a90a365f2882a154d031d0"
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
Reference in New Issue
Block a user