fix(editor): Use pinned data to resolve expressions in unexecuted nodes (#9693)
Co-authored-by: Milorad Filipovic <milorad@n8n.io> Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
135
cypress/e2e/2111-ado-support-pinned-data-in-expressions.cy.ts
Normal file
135
cypress/e2e/2111-ado-support-pinned-data-in-expressions.cy.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
describe('ADO-2111 expressions should support pinned data', () => {
|
||||
beforeEach(() => {
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
it('supports pinned data in expressions unexecuted and executed parent nodes', () => {
|
||||
cy.createFixtureWorkflow('Test_workflow_pinned_data_in_expressions.json', 'Expressions');
|
||||
|
||||
// test previous node unexecuted
|
||||
workflowPage.actions.openNode('NotPinnedWithExpressions');
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(0)
|
||||
.should('include.text', 'Joe\nJoe\nJoan\nJoan\nJoe\nJoan\n\nJoe\nJoan\n\nJoe');
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(1)
|
||||
.should('contain.text', '0,0\nJoe\n\nJoe\n\nJoe\n\nJoe\nJoe');
|
||||
|
||||
// test can resolve correctly based on item
|
||||
ndv.actions.switchInputMode('Table');
|
||||
|
||||
ndv.getters.inputTableRow(2).realHover();
|
||||
cy.wait(50);
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(0)
|
||||
.should('include.text', 'Joe\nJoe\nJoan\nJoan\nJoe\nJoan\n\nJoe\nJoan\n\nJoe');
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(1)
|
||||
.should('contain.text', '0,1\nJoan\n\nJoan\n\nJoan\n\nJoan\nJoan');
|
||||
|
||||
// test previous node executed
|
||||
ndv.actions.execute();
|
||||
ndv.getters.inputTableRow(1).realHover();
|
||||
cy.wait(50);
|
||||
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(0)
|
||||
.should('include.text', 'Joe\nJoe\nJoan\nJoan\nJoe\nJoan\n\nJoe\nJoan\n\nJoe');
|
||||
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(1)
|
||||
.should('contain.text', '0,0\nJoe\n\nJoe\n\nJoe\n\nJoe\nJoe');
|
||||
|
||||
ndv.getters.inputTableRow(2).realHover();
|
||||
cy.wait(50);
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(0)
|
||||
.should('include.text', 'Joe\nJoe\nJoan\nJoan\nJoe\nJoan\n\nJoe\nJoan\n\nJoe');
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(1)
|
||||
.should('contain.text', '0,1\nJoan\n\nJoan\n\nJoan\n\nJoan\nJoan');
|
||||
|
||||
// check it resolved correctly on the backend
|
||||
ndv.getters
|
||||
.outputTbodyCell(1, 0)
|
||||
.should('contain.text', 'Joe\\nJoe\\nJoan\\nJoan\\nJoe\\nJoan\\n\\nJoe\\nJoan\\n\\nJoe');
|
||||
|
||||
ndv.getters
|
||||
.outputTbodyCell(2, 0)
|
||||
.should('contain.text', 'Joe\\nJoe\\nJoan\\nJoan\\nJoe\\nJoan\\n\\nJoe\\nJoan\\n\\nJoe');
|
||||
|
||||
ndv.getters
|
||||
.outputTbodyCell(1, 1)
|
||||
.should('contain.text', '0,0\\nJoe\\n\\nJoe\\n\\nJoe\\n\\nJoe\\nJoe');
|
||||
|
||||
ndv.getters
|
||||
.outputTbodyCell(2, 1)
|
||||
.should('contain.text', '0,1\\nJoan\\n\\nJoan\\n\\nJoan\\n\\nJoan\\nJoan');
|
||||
});
|
||||
|
||||
it('resets expressions after node is unpinned', () => {
|
||||
cy.createFixtureWorkflow('Test_workflow_pinned_data_in_expressions.json', 'Expressions');
|
||||
|
||||
// test previous node unexecuted
|
||||
workflowPage.actions.openNode('NotPinnedWithExpressions');
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(0)
|
||||
.should('include.text', 'Joe\nJoe\nJoan\nJoan\nJoe\nJoan\n\nJoe\nJoan\n\nJoe');
|
||||
ndv.getters
|
||||
.parameterExpressionPreview('value')
|
||||
.eq(1)
|
||||
.should('contain.text', '0,0\nJoe\n\nJoe\n\nJoe\n\nJoe\nJoe');
|
||||
|
||||
ndv.actions.close();
|
||||
|
||||
// unpin pinned node
|
||||
workflowPage.getters
|
||||
.canvasNodeByName('PinnedSet')
|
||||
.eq(0)
|
||||
.find('.node-pin-data-icon')
|
||||
.should('exist');
|
||||
workflowPage.getters.canvasNodeByName('PinnedSet').eq(0).click();
|
||||
workflowPage.actions.hitPinNodeShortcut();
|
||||
workflowPage.getters
|
||||
.canvasNodeByName('PinnedSet')
|
||||
.eq(0)
|
||||
.find('.node-pin-data-icon')
|
||||
.should('not.exist');
|
||||
|
||||
workflowPage.actions.openNode('NotPinnedWithExpressions');
|
||||
ndv.getters.nodeParameters().find('parameter-expression-preview-value').should('not.exist');
|
||||
|
||||
ndv.getters.parameterInput('value').eq(0).click();
|
||||
ndv.getters
|
||||
.inlineExpressionEditorOutput()
|
||||
.should(
|
||||
'have.text',
|
||||
'[Execute node ‘PinnedSet’ for preview][Execute node ‘PinnedSet’ for preview][Execute node ‘PinnedSet’ for preview][Execute node ‘PinnedSet’ for preview][Execute node ‘PinnedSet’ for preview][Execute node ‘PinnedSet’ for preview][Execute previous nodes for preview][Execute previous nodes for preview][undefined]',
|
||||
);
|
||||
|
||||
// close open expression
|
||||
ndv.getters.inputLabel().eq(0).click();
|
||||
|
||||
ndv.getters.parameterInput('value').eq(1).click();
|
||||
ndv.getters
|
||||
.inlineExpressionEditorOutput()
|
||||
.should(
|
||||
'have.text',
|
||||
'0,0[Execute node ‘PinnedSet’ for preview][Execute node ‘PinnedSet’ for preview][Execute previous nodes for preview][Execute previous nodes for preview][Execute previous nodes for preview]',
|
||||
);
|
||||
});
|
||||
});
|
||||
112
cypress/fixtures/Test_workflow_pinned_data_in_expressions.json
Normal file
112
cypress/fixtures/Test_workflow_pinned_data_in_expressions.json
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"meta": {
|
||||
"instanceId": "5bd32b91ed2a88e542012920460f736c3687a32fbb953718f6952d182231c0ff"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "a482f1fd-4815-4da4-a733-7beafb43c500",
|
||||
"name": "static",
|
||||
"value": "={{ $('PinnedSet').first().json.firstName }}\n{{ $('PinnedSet').itemMatching(0).json.firstName }}\n{{ $('PinnedSet').itemMatching(1).json.firstName }}\n{{ $('PinnedSet').last().json.firstName }}\n{{ $('PinnedSet').all()[0].json.firstName }}\n{{ $('PinnedSet').all()[1].json.firstName }}\n\n{{ $input.first().json.firstName }}\n{{ $input.last().json.firstName }}\n\n{{ $items()[0].json.firstName }}",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"id": "2c973f2a-7ca0-41bc-903c-7174bee251b0",
|
||||
"name": "variable",
|
||||
"value": "={{ $runIndex }},{{ $itemIndex }}\n{{ $node['PinnedSet'].json.firstName }}\n\n{{ $('PinnedSet').item.json.firstName }}\n\n{{ $input.item.json.firstName }}\n\n{{ $json.firstName }}\n{{ $data.firstName }}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "ac55ee16-4598-48bf-ace3-a48fed1d4ff3",
|
||||
"name": "NotPinnedWithExpressions",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.3,
|
||||
"position": [
|
||||
1600,
|
||||
640
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "3058c300-b377-41b7-9c90-a01372f9b581",
|
||||
"name": "firstName",
|
||||
"value": "Joe",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"id": "bb871662-c23c-4234-ac0c-b78c279bbf34",
|
||||
"name": "lastName",
|
||||
"value": "Smith",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "300a3888-cc2f-4e61-8578-b0adbcf33450",
|
||||
"name": "PinnedSet",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.3,
|
||||
"position": [
|
||||
1340,
|
||||
640
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "426ff39a-3408-48b4-899f-60db732675f8",
|
||||
"name": "Start",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"position": [
|
||||
1100,
|
||||
640
|
||||
],
|
||||
"typeVersion": 1
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"PinnedSet": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "NotPinnedWithExpressions",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Start": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "PinnedSet",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"pinData": {
|
||||
"PinnedSet": [
|
||||
{
|
||||
"firstName": "Joe",
|
||||
"lastName": "Smith"
|
||||
},
|
||||
{
|
||||
"firstName": "Joan",
|
||||
"lastName": "Summers"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ export class NDV extends BasePage {
|
||||
nodeOutputHint: () => cy.getByTestId('ndv-output-run-node-hint'),
|
||||
savePinnedDataButton: () =>
|
||||
this.getters.runDataPaneHeader().find('button').filter(':visible').contains('Save'),
|
||||
inputLabel: () => cy.getByTestId('input-label'),
|
||||
outputTableRows: () => this.getters.outputDataContainer().find('table tr'),
|
||||
outputTableHeaders: () => this.getters.outputDataContainer().find('table thead th'),
|
||||
outputTableHeaderByText: (text: string) => this.getters.outputTableHeaders().contains(text),
|
||||
|
||||
Reference in New Issue
Block a user