fix(editor): Fix bug with node names with certain characters (#8013)

## Summary
Fixes the issue that dots and other special characters can not be used
in node-names


## Related tickets and issues

https://linear.app/n8n/issue/ADO-1244/nodes-wont-output-data-if-the-name-contains-some-characters

https://community.n8n.io/t/bug-report-name-of-node-affects-output-data/31674
https://community.n8n.io/t/stripe-output-data/32418/1
https://community.n8n.io/t/monday-com-returning-items-but-no-data/31834
https://community.n8n.io/t/no-data-while-there-is-actually-data/32563
https://community.n8n.io/t/bug-report-periods-in-node-names/34119
https://github.com/n8n-io/n8n/issues/7896


## Review / Merge checklist
- [ ] PR title and summary are descriptive. **Remember, the title
automatically goes into the changelog. Use `(no-changelog)` otherwise.**
([conventions](https://github.com/n8n-io/n8n/blob/master/.github/pull_request_title_conventions.md))
- [ ] [Docs updated](https://github.com/n8n-io/n8n-docs) or follow-up
ticket created.
- [ ] Tests included.
> A bug is not considered fixed, unless a test is added to prevent it
from happening again.
   > A feature is not complete without tests.

---------

Co-authored-by: Alex Grozav <alex@grozav.com>
This commit is contained in:
Jan Oberhauser 2023-12-13 15:57:01 +01:00 committed by GitHub
parent 8a5343401d
commit 26f0d57f5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 183 additions and 1 deletions

View file

@ -0,0 +1,182 @@
import { setActivePinia } from 'pinia';
import { createTestingPinia } from '@pinia/testing';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
import { createTestNode } from '@/__tests__/mocks';
import { useWorkflowsStore } from '@/stores/workflows.store';
vi.mock('@/stores/workflows.store', () => ({
useWorkflowsStore: vi.fn(),
}));
describe('useNodeHelpers()', () => {
beforeAll(() => {
setActivePinia(createTestingPinia());
});
afterEach(() => {
vi.clearAllMocks();
});
describe('getNodeInputData()', () => {
it('should return an empty array when node is null', () => {
const { getNodeInputData } = useNodeHelpers();
const result = getNodeInputData(null);
expect(result).toEqual([]);
});
it('should return an empty array when workflowsStore.getWorkflowExecution() is null', () => {
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: null,
} as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: 'test',
type: 'test',
});
const result = getNodeInputData(node);
expect(result).toEqual([]);
});
it('should return an empty array when workflowsStore.getWorkflowExecution() is null', () => {
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: null,
} as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: 'test',
type: 'test',
});
const result = getNodeInputData(node);
expect(result).toEqual([]);
});
it('should return an empty array when resultData is not available', () => {
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: {
data: {
resultData: null,
},
},
} as unknown as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: 'test',
type: 'test',
});
const result = getNodeInputData(node);
expect(result).toEqual([]);
});
it('should return an empty array when taskData is unavailable', () => {
const nodeName = 'Code';
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: {
data: {
resultData: {
runData: {
[nodeName]: [],
},
},
},
},
} as unknown as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: nodeName,
type: 'test',
});
const result = getNodeInputData(node);
expect(result).toEqual([]);
});
it('should return an empty array when taskData.data is unavailable', () => {
const nodeName = 'Code';
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: {
data: {
resultData: {
runData: {
[nodeName]: [{ data: undefined }],
},
},
},
},
} as unknown as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: nodeName,
type: 'test',
});
const result = getNodeInputData(node);
expect(result).toEqual([]);
});
it('should return input data from inputOverride', () => {
const nodeName = 'Code';
const data = { hello: 'world' };
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: {
data: {
resultData: {
runData: {
[nodeName]: [
{
inputOverride: {
main: [data],
},
},
],
},
},
},
},
} as unknown as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: nodeName,
type: 'test',
});
const result = getNodeInputData(node, 0, 0, 'input');
expect(result).toEqual(data);
});
it.each(['example', 'example.withdot', 'example.with.dots', 'example.with.dots and spaces'])(
'should return input data for "%s" node name, with given connection type and output index',
(nodeName) => {
const data = { hello: 'world' };
vi.mocked(useWorkflowsStore).mockReturnValue({
getWorkflowExecution: {
data: {
resultData: {
runData: {
[nodeName]: [
{
data: {
main: [data],
},
},
],
},
},
},
},
} as unknown as ReturnType<typeof useWorkflowsStore>);
const { getNodeInputData } = useNodeHelpers();
const node = createTestNode({
name: nodeName,
type: 'test',
});
const result = getNodeInputData(node);
expect(result).toEqual(data);
},
);
});
});

View file

@ -539,7 +539,7 @@ export function useNodeHelpers() {
}
const runData = executionData.resultData.runData;
const taskData = get(runData, `[${node.name}][${runIndex}]`);
const taskData = get(runData, [node.name, runIndex]);
if (!taskData) {
return [];
}