mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-22 12:19:09 +00:00
test: 14-mapping tests migration (#18858)
This commit is contained in:
@@ -23,8 +23,8 @@ test.describe('Canvas Actions', () => {
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.fillNodeCreatorSearchBar(CODE_NODE_NAME);
|
||||
await n8n.page.keyboard.press('Enter');
|
||||
await n8n.canvas.nodeCreatorSubItem(CODE_NODE_DISPLAY_NAME).click();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await n8n.canvas.clickNodeCreatorItemName(CODE_NODE_DISPLAY_NAME);
|
||||
await n8n.page.keyboard.press('Enter');
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(1);
|
||||
@@ -61,7 +61,7 @@ test.describe('Canvas Actions', () => {
|
||||
test('should add disconnected node if nothing is selected', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.deselectAll();
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(0);
|
||||
@@ -70,7 +70,7 @@ test.describe('Canvas Actions', () => {
|
||||
test('should add node between two connected nodes', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.nodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(1);
|
||||
@@ -96,7 +96,7 @@ test.describe('Canvas Actions', () => {
|
||||
test('should delete connections by clicking on the delete button', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.nodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
await n8n.canvas.deleteConnectionBetweenNodes(
|
||||
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
|
||||
CODE_NODE_DISPLAY_NAME,
|
||||
@@ -119,7 +119,7 @@ test.describe('Canvas Actions', () => {
|
||||
|
||||
test('should disable and enable node', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
|
||||
const disableButton = n8n.canvas.nodeDisableButton(CODE_NODE_DISPLAY_NAME);
|
||||
await disableButton.click();
|
||||
@@ -133,7 +133,7 @@ test.describe('Canvas Actions', () => {
|
||||
|
||||
test('should delete node', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
await n8n.canvas.deleteNodeByName(CODE_NODE_DISPLAY_NAME);
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(1);
|
||||
@@ -143,7 +143,7 @@ test.describe('Canvas Actions', () => {
|
||||
|
||||
test('should copy selected nodes', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
await n8n.canvasComposer.selectAllAndCopy();
|
||||
await n8n.canvas.nodeByName(CODE_NODE_DISPLAY_NAME).click();
|
||||
await n8n.canvasComposer.copySelectedNodesWithToast();
|
||||
@@ -153,7 +153,7 @@ test.describe('Canvas Actions', () => {
|
||||
|
||||
test('should select/deselect all nodes', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
await n8n.canvas.selectAll();
|
||||
|
||||
await expect(n8n.canvas.selectedNodes()).toHaveCount(2);
|
||||
@@ -165,7 +165,7 @@ test.describe('Canvas Actions', () => {
|
||||
test('should select nodes using arrow keys', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.nodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
await n8n.canvas.getCanvasNodes().first().waitFor();
|
||||
await n8n.canvas.navigateNodesWithArrows('left');
|
||||
|
||||
@@ -180,7 +180,7 @@ test.describe('Canvas Actions', () => {
|
||||
test('should select nodes using shift and arrow keys', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.nodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: CODE_NODE_DISPLAY_NAME, closeNDV: true });
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
|
||||
await n8n.canvas.getCanvasNodes().first().waitFor();
|
||||
await n8n.canvas.extendSelectionWithArrows('left');
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ test.describe('Data pinning', () => {
|
||||
await n8n.ndv.execute();
|
||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
||||
|
||||
const prevValue = await n8n.ndv.getOutputTbodyCell(1, 0).textContent();
|
||||
const prevValue = await n8n.ndv.getOutputTbodyCell(0, 0).textContent();
|
||||
|
||||
await n8n.ndv.togglePinData();
|
||||
await n8n.ndv.close();
|
||||
@@ -48,7 +48,7 @@ test.describe('Data pinning', () => {
|
||||
await n8n.canvas.clickExecuteWorkflowButton();
|
||||
await n8n.canvas.openNode(NODES.SCHEDULE_TRIGGER);
|
||||
|
||||
await expect(n8n.ndv.getOutputTbodyCell(1, 0)).toHaveText(prevValue ?? '');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toHaveText(prevValue ?? '');
|
||||
});
|
||||
|
||||
test('should be able to set custom pinned data', async ({ n8n }) => {
|
||||
@@ -63,14 +63,14 @@ test.describe('Data pinning', () => {
|
||||
await expect(n8n.ndv.getOutputTableRows()).toHaveCount(2);
|
||||
await expect(n8n.ndv.getOutputTableHeaders()).toHaveCount(2);
|
||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('test');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(1, 0)).toContainText('1');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
||||
|
||||
await n8n.ndv.close();
|
||||
await n8n.canvas.clickSaveWorkflowButton();
|
||||
await n8n.canvas.openNode(NODES.SCHEDULE_TRIGGER);
|
||||
|
||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('test');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(1, 0)).toContainText('1');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
||||
});
|
||||
|
||||
test('should display pin data edit button for Webhook node', async ({ n8n }) => {
|
||||
@@ -102,7 +102,7 @@ test.describe('Data pinning', () => {
|
||||
await n8n.canvas.openNode('Edit Fields1');
|
||||
|
||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('test');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(1, 0)).toContainText('1');
|
||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -212,10 +212,7 @@ test.describe('Data pinning', () => {
|
||||
}) => {
|
||||
await setupRequirements(webhookTestRequirements);
|
||||
await expect(n8n.canvas.getWorkflowSaveButton()).toContainText('Saved');
|
||||
await n8n.page.waitForTimeout(500);
|
||||
await n8n.canvas.activateWorkflow();
|
||||
await n8n.page.waitForTimeout(500);
|
||||
|
||||
const webhookUrl = '/webhook/b0d79ddb-df2d-49b1-8555-9fa2b482608f';
|
||||
const response = await n8n.ndv.makeWebhookRequest(webhookUrl);
|
||||
expect(response.status(), 'Webhook response is: ' + (await response.text())).toBe(200);
|
||||
|
||||
367
packages/testing/playwright/tests/ui/14-mapping.spec.ts
Normal file
367
packages/testing/playwright/tests/ui/14-mapping.spec.ts
Normal file
@@ -0,0 +1,367 @@
|
||||
import { test, expect } from '../../fixtures/base';
|
||||
|
||||
test.describe('Data Mapping', () => {
|
||||
test.describe
|
||||
.serial('Expression Preview', () => {
|
||||
test('maps expressions from table json, and resolves value based on hover', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
// This test is marked as serial because hover/tooltips are unreliable when running in parallel against a single server due to resource contention.
|
||||
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
await n8n.ndv.switchInputMode('Table');
|
||||
|
||||
await expect(n8n.ndv.getInputTable()).toBeVisible();
|
||||
|
||||
await expect(n8n.ndv.getParameterInputField('name')).toHaveValue('other');
|
||||
await expect(n8n.ndv.getParameterInputField('value')).toHaveValue('');
|
||||
|
||||
const countCell = n8n.ndv.getInputTableCellSpan(0, 0, 'count');
|
||||
await expect(countCell).toBeVisible();
|
||||
|
||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||
await n8n.interactions.precisionDragToTarget(countCell, valueParameter, 'bottom');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
'{{ $json.input[0].count }}',
|
||||
);
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||
|
||||
await n8n.ndv.getInputTbodyCell(0, 0).hover();
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||
|
||||
await n8n.ndv.getInputTbodyCell(1, 0).hover();
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('1');
|
||||
|
||||
await n8n.ndv.execute();
|
||||
|
||||
await expect(n8n.ndv.getOutputTable()).toBeVisible();
|
||||
|
||||
await n8n.ndv.getOutputTbodyCell(0, 0).hover();
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||
|
||||
await n8n.ndv.getOutputTbodyCell(1, 0).hover();
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('1');
|
||||
});
|
||||
});
|
||||
test('maps expressions from json view', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
await n8n.ndv.switchInputMode('JSON');
|
||||
|
||||
const expectedJsonText =
|
||||
'[{"input": [{"count": 0,"with space": "!!","with.dot": "!!","with"quotes": "!!"}]},{"input": [{"count": 1}]}]';
|
||||
await expect(n8n.ndv.getInputPanel().getByText(expectedJsonText)).toBeVisible();
|
||||
|
||||
await expect(n8n.ndv.getJsonDataContainer()).toBeVisible();
|
||||
|
||||
const inputSpan = n8n.ndv.getInputJsonProperty('input');
|
||||
await expect(inputSpan).toBeVisible();
|
||||
|
||||
const valueParameterInput = n8n.ndv.getParameterInput('value');
|
||||
await expect(valueParameterInput).toBeVisible();
|
||||
|
||||
await inputSpan.dragTo(valueParameterInput);
|
||||
|
||||
const expressionEditor = n8n.ndv.getInlineExpressionEditorInput();
|
||||
await expect(expressionEditor).toBeVisible();
|
||||
await expect(expressionEditor).toHaveText('{{ $json.input }}');
|
||||
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('Array:');
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('"count": 0');
|
||||
|
||||
const countSpan = n8n.ndv.getInputJsonPropertyContaining('count');
|
||||
await expect(countSpan).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(
|
||||
countSpan,
|
||||
n8n.ndv.getInlineExpressionEditorInput(),
|
||||
'bottom',
|
||||
);
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
'{{ $json.input }}{{ $json.input[0].count }}',
|
||||
);
|
||||
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
const previewElement = n8n.ndv.getParameterExpressionPreviewValue();
|
||||
await expect(previewElement).toBeVisible();
|
||||
});
|
||||
|
||||
test('maps expressions from previous nodes', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set1');
|
||||
await n8n.ndv.executePrevious();
|
||||
|
||||
const scheduleNode = n8n.ndv.getInputPanel().getByText('Schedule Trigger');
|
||||
await expect(scheduleNode).toBeVisible();
|
||||
await scheduleNode.click();
|
||||
|
||||
const schemaItem = n8n.ndv.getInputSchemaItem('count');
|
||||
await expect(schemaItem).toBeVisible();
|
||||
|
||||
const valueParameterInput = n8n.ndv.getParameterInput('value');
|
||||
await expect(valueParameterInput).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(schemaItem, valueParameterInput, 'top');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
"{{ $('Schedule Trigger').item.json.input[0].count }}",
|
||||
);
|
||||
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await n8n.ndv.switchInputMode('Table');
|
||||
await n8n.ndv.selectInputNode('Schedule Trigger');
|
||||
|
||||
const headerElement = n8n.ndv.getInputTableHeader(0);
|
||||
await expect(headerElement).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(
|
||||
headerElement,
|
||||
n8n.ndv.getInlineExpressionEditorInput(),
|
||||
'top',
|
||||
);
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
"{{ $('Schedule Trigger').item.json.input }}{{ $('Schedule Trigger').item.json.input[0].count }}",
|
||||
);
|
||||
|
||||
await n8n.ndv.selectInputNode('Set');
|
||||
});
|
||||
test('maps expressions from table header', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow-actions_paste-data.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
await n8n.ndv.executePrevious();
|
||||
await n8n.ndv.switchInputMode('Table');
|
||||
|
||||
await expect(n8n.ndv.getInputTable()).toBeVisible();
|
||||
|
||||
const addValueButton = n8n.ndv.getAddValueButton();
|
||||
await expect(addValueButton).toBeVisible();
|
||||
await addValueButton.click();
|
||||
|
||||
await n8n.page.getByRole('option', { name: 'String' }).click();
|
||||
|
||||
await expect(n8n.ndv.getParameterInputField('name')).toHaveValue('propertyName');
|
||||
await expect(n8n.ndv.getParameterInputField('value')).toHaveValue('');
|
||||
|
||||
const firstHeader = n8n.ndv.getInputTableHeader(0);
|
||||
await expect(firstHeader).toBeVisible();
|
||||
|
||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||
await n8n.interactions.precisionDragToTarget(firstHeader, valueParameter, 'bottom');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toBeVisible();
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText('{{ $json.timestamp }}');
|
||||
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
const currentYear = new Date().getFullYear().toString();
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText(currentYear);
|
||||
|
||||
const secondHeader = n8n.ndv.getInputTableHeader(1);
|
||||
await expect(secondHeader).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(
|
||||
secondHeader,
|
||||
n8n.ndv.getInlineExpressionEditorInput(),
|
||||
'top',
|
||||
);
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
"{{ $json['Readable date'] }}{{ $json.timestamp }}",
|
||||
);
|
||||
});
|
||||
|
||||
test('maps expressions from schema view', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
|
||||
await n8n.ndv.getParameterInputField('value').clear();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
const countSchemaItem = n8n.ndv.getInputSchemaItem('count');
|
||||
await expect(countSchemaItem).toBeVisible();
|
||||
|
||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||
await n8n.interactions.precisionDragToTarget(countSchemaItem, valueParameter, 'bottom');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText('{{ $json.input[0].count }}');
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||
|
||||
const inputSchemaItem = n8n.ndv.getInputSchemaItem('input');
|
||||
await expect(inputSchemaItem).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'top');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
'{{ $json.input }}{{ $json.input[0].count }}',
|
||||
);
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('[object Object]0');
|
||||
});
|
||||
|
||||
test('maps keys to path', async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
await n8n.canvas.addNode('Manual Trigger');
|
||||
await n8n.canvas.openNode('When clicking ‘Execute workflow’');
|
||||
|
||||
await n8n.ndv.setPinnedData([
|
||||
{
|
||||
input: [
|
||||
{
|
||||
'hello.world': {
|
||||
'my count': 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: [
|
||||
{
|
||||
'hello.world': {
|
||||
'my count': 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
await n8n.ndv.close();
|
||||
|
||||
await n8n.canvas.addNode('Sort');
|
||||
|
||||
const addFieldButton = n8n.ndv.getAddFieldToSortByButton();
|
||||
await addFieldButton.click();
|
||||
|
||||
const myCountSpan = n8n.ndv.getInputSchemaItem('my count');
|
||||
await expect(myCountSpan).toBeVisible();
|
||||
|
||||
const fieldNameParameter = n8n.ndv.getParameterInput('fieldName');
|
||||
await n8n.interactions.precisionDragToTarget(myCountSpan, fieldNameParameter, 'bottom');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toBeHidden();
|
||||
await expect(n8n.ndv.getParameterInputField('fieldName')).toHaveValue(
|
||||
"input[0]['hello.world']['my count']",
|
||||
);
|
||||
});
|
||||
|
||||
test('maps expressions to updated fields correctly', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
|
||||
await n8n.ndv.fillParameterInputByName('value', 'delete me');
|
||||
await n8n.ndv.fillParameterInputByName('name', 'test');
|
||||
await n8n.ndv.getParameterInputField('name').blur();
|
||||
|
||||
await n8n.ndv.fillParameterInputByName('value', 'fun');
|
||||
await n8n.ndv.getParameterInputField('value').clear();
|
||||
|
||||
const countSchemaItem = n8n.ndv.getInputSchemaItem('count');
|
||||
await expect(countSchemaItem).toBeVisible();
|
||||
|
||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||
await n8n.interactions.precisionDragToTarget(countSchemaItem, valueParameter, 'bottom');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText('{{ $json.input[0].count }}');
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||
|
||||
const inputSchemaItem = n8n.ndv.getInputSchemaItem('input');
|
||||
await expect(inputSchemaItem).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'top');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
'{{ $json.input }}{{ $json.input[0].count }}',
|
||||
);
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('[object Object]0');
|
||||
});
|
||||
|
||||
test('renders expression preview when a previous node is selected', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
|
||||
await n8n.ndv.fillParameterInputByName('value', 'test_value');
|
||||
await n8n.ndv.fillParameterInputByName('name', 'test_name');
|
||||
await n8n.ndv.close();
|
||||
|
||||
await n8n.canvas.openNode('Set1');
|
||||
await n8n.ndv.executePrevious();
|
||||
await n8n.ndv.switchInputMode('Table');
|
||||
|
||||
const firstHeader = n8n.ndv.getInputTableHeader(0);
|
||||
await expect(firstHeader).toBeVisible();
|
||||
|
||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||
await n8n.interactions.precisionDragToTarget(firstHeader, valueParameter, 'bottom');
|
||||
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('test_value');
|
||||
|
||||
await n8n.ndv.selectInputNode('Schedule Trigger');
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('test_value');
|
||||
});
|
||||
|
||||
test('shows you can drop to inputs, including booleans', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
|
||||
await expect(n8n.ndv.getParameterSwitch('includeOtherFields')).toBeVisible();
|
||||
await expect(n8n.ndv.getParameterTextInput('includeOtherFields')).toBeHidden();
|
||||
|
||||
const countSpan = n8n.ndv.getInputSchemaItem('count');
|
||||
await expect(countSpan).toBeVisible();
|
||||
|
||||
await countSpan.hover();
|
||||
await n8n.page.mouse.down();
|
||||
await n8n.page.mouse.move(100, 100);
|
||||
|
||||
await expect(n8n.ndv.getParameterSwitch('includeOtherFields')).toBeHidden();
|
||||
await expect(n8n.ndv.getParameterTextInput('includeOtherFields')).toBeVisible();
|
||||
|
||||
const includeOtherFieldsInput = n8n.ndv.getParameterTextInput('includeOtherFields');
|
||||
await expect(includeOtherFieldsInput).toHaveCSS('border', /dashed.*rgb\(90, 76, 194\)/);
|
||||
|
||||
const valueInput = n8n.ndv.getParameterTextInput('value');
|
||||
await expect(valueInput).toHaveCSS('border', /dashed.*rgb\(90, 76, 194\)/);
|
||||
|
||||
await n8n.page.mouse.up();
|
||||
});
|
||||
|
||||
test('maps expressions to a specific location in the editor', async ({ n8n }) => {
|
||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||
await n8n.canvas.openNode('Set');
|
||||
|
||||
await n8n.ndv.fillParameterInputByName('value', '=');
|
||||
await n8n.ndv.getInlineExpressionEditorContent().fill('hello world\n\nnewline');
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
const countSchemaItem = n8n.ndv.getInputSchemaItem('count');
|
||||
await expect(countSchemaItem).toBeVisible();
|
||||
|
||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||
await n8n.interactions.precisionDragToTarget(countSchemaItem, valueParameter, 'top');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
'{{ $json.input[0].count }}hello worldnewline',
|
||||
);
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText(
|
||||
'0hello world\n\nnewline',
|
||||
);
|
||||
|
||||
const inputSchemaItem = n8n.ndv.getInputSchemaItem('input');
|
||||
await expect(inputSchemaItem).toBeVisible();
|
||||
|
||||
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'center');
|
||||
|
||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||
'{{ $json.input[0].count }}hello world{{ $json.input }}newline',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -69,7 +69,7 @@ test.describe('Projects', () => {
|
||||
|
||||
await n8n.ndv.selectWorkflowResource(`Create a Sub-Workflow in '${projectName}'`);
|
||||
|
||||
const subn8n = new n8nPage(await subWorkflowPagePromise);
|
||||
const subn8n = new n8nPage(await subWorkflowPagePromise, n8n.api);
|
||||
|
||||
await subn8n.ndv.clickBackToCanvasButton();
|
||||
|
||||
@@ -95,7 +95,7 @@ test.describe('Projects', () => {
|
||||
await expect(subn8n.page.getByRole('heading', { name: 'My Sub-Workflow' })).toBeVisible();
|
||||
|
||||
// Navigate to Credentials
|
||||
await subn8n.page.getByRole('link', { name: 'Credentials' }).click();
|
||||
await subn8n.page.getByRole('link', { name: 'Credentials', exact: true }).click();
|
||||
|
||||
// Assert that the credential is in the list
|
||||
await expect(subn8n.page.locator('[data-test-id="resources-list-item"]')).toHaveCount(1);
|
||||
|
||||
@@ -13,7 +13,7 @@ test.describe('Code node', () => {
|
||||
await n8n.goHome();
|
||||
await n8n.workflows.clickAddWorkflowButton();
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNodeWithSubItem(CODE_NODE_NAME, CODE_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript' });
|
||||
});
|
||||
|
||||
test('should show correct placeholders switching modes', async ({ n8n }) => {
|
||||
@@ -54,21 +54,21 @@ test.describe('Code node', () => {
|
||||
});
|
||||
|
||||
test('should allow switching between sibling code nodes', async ({ n8n }) => {
|
||||
await n8n.ndv.getCodeEditor().fill("console.log('code node 1')");
|
||||
await n8n.ndv.getCodeEditor().fill("console.log('Code in JavaScript1')");
|
||||
await n8n.ndv.close();
|
||||
|
||||
await n8n.canvas.addNodeWithSubItem(CODE_NODE_NAME, CODE_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript' });
|
||||
|
||||
await n8n.ndv.getCodeEditor().fill("console.log('code node 2')");
|
||||
await n8n.ndv.getCodeEditor().fill("console.log('Code in JavaScript2')");
|
||||
await n8n.ndv.close();
|
||||
|
||||
await n8n.canvas.openNode(CODE_NODE_DISPLAY_NAME);
|
||||
|
||||
await n8n.ndv.clickFloatingNode(CODE_NODE_DISPLAY_NAME + '1');
|
||||
await expect(n8n.ndv.getCodeEditor()).toContainText("console.log('code node 2')");
|
||||
await expect(n8n.ndv.getCodeEditor()).toContainText("console.log('Code in JavaScript2')");
|
||||
|
||||
await n8n.ndv.clickFloatingNode(CODE_NODE_DISPLAY_NAME);
|
||||
await expect(n8n.ndv.getCodeEditor()).toContainText("console.log('code node 1')");
|
||||
await expect(n8n.ndv.getCodeEditor()).toContainText("console.log('Code in JavaScript1')");
|
||||
});
|
||||
|
||||
test('should show lint errors in `runOnceForAllItems` mode', async ({ n8n }) => {
|
||||
@@ -89,25 +89,31 @@ return
|
||||
'`.itemMatching()` expects an item index to be passed in as its argument.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('should show lint errors in `runOnceForEachItem` mode', async ({ n8n }) => {
|
||||
await n8n.ndv.getParameterInput('mode').click();
|
||||
await n8n.page.getByRole('option', { name: 'Run Once for Each Item' }).click();
|
||||
test.describe
|
||||
.serial('Run Once for Each Item', () => {
|
||||
test('should show lint errors in `runOnceForEachItem` mode', async ({ n8n }) => {
|
||||
await n8n.start.fromHome();
|
||||
await n8n.workflows.clickAddWorkflowButton();
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript' });
|
||||
await n8n.ndv.toggleCodeMode('Run Once for Each Item');
|
||||
|
||||
await n8n.ndv.getCodeEditor().fill(`$input.itemMatching()
|
||||
await n8n.ndv.getCodeEditor().fill(`$input.itemMatching()
|
||||
$input.all()
|
||||
$input.first()
|
||||
$input.item()
|
||||
|
||||
return []
|
||||
`);
|
||||
await expect(n8n.ndv.getLintErrors()).toHaveCount(5);
|
||||
await n8n.ndv.getParameterInput('jsCode').getByText('all').hover();
|
||||
await expect(n8n.ndv.getLintTooltip()).toContainText(
|
||||
"Method `$input.all()` is only available in the 'Run Once for All Items' mode.",
|
||||
);
|
||||
await expect(n8n.ndv.getLintErrors()).toHaveCount(7);
|
||||
await n8n.ndv.getParameterInput('jsCode').getByText('all').hover();
|
||||
await expect(n8n.ndv.getLintTooltip()).toContainText(
|
||||
"Method `$input.all()` is only available in the 'Run Once for All Items' mode.",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Ask AI', () => {
|
||||
test.describe('Enabled', () => {
|
||||
@@ -116,10 +122,7 @@ return []
|
||||
await n8n.goHome();
|
||||
await n8n.workflows.clickAddWorkflowButton();
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.clickNodeCreatorPlusButton();
|
||||
await n8n.canvas.fillNodeCreatorSearchBar(CODE_NODE_NAME);
|
||||
await n8n.page.keyboard.press('Enter');
|
||||
await n8n.canvas.clickNodeCreatorItemName(CODE_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript' });
|
||||
});
|
||||
|
||||
test('tab should exist if experiment selected and be selectable', async ({ n8n }) => {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import {
|
||||
MANUAL_TRIGGER_NODE_NAME,
|
||||
MANUAL_TRIGGER_NODE_DISPLAY_NAME,
|
||||
CODE_NODE_NAME,
|
||||
CODE_NODE_DISPLAY_NAME,
|
||||
} from '../../config/constants';
|
||||
import { test, expect } from '../../fixtures/base';
|
||||
} from '../../../config/constants';
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Canvas Node Actions', () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
@@ -57,9 +55,11 @@ test.describe('Canvas Node Actions', () => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.fillNodeCreatorSearchBar(CODE_NODE_NAME);
|
||||
await n8n.canvas.fillNodeCreatorSearchBar('Code');
|
||||
await n8n.page.keyboard.press('Enter');
|
||||
|
||||
await n8n.canvas.clickNodeCreatorItemName('Code in JavaScript');
|
||||
await n8n.page.keyboard.press('Enter');
|
||||
await n8n.canvas.nodeCreatorSubItem(CODE_NODE_DISPLAY_NAME).click();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
@@ -69,11 +69,7 @@ test.describe('Canvas Node Actions', () => {
|
||||
test('should add disconnected node when nothing selected', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.deselectAll();
|
||||
await n8n.canvas.clickNodeCreatorPlusButton();
|
||||
await n8n.canvas.fillNodeCreatorSearchBar(CODE_NODE_NAME);
|
||||
await n8n.page.keyboard.press('Enter');
|
||||
await n8n.canvas.nodeCreatorSubItem(CODE_NODE_DISPLAY_NAME).click();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await n8n.canvas.addNode('Code', { action: 'Code in JavaScript', closeNDV: true });
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(0);
|
||||
});
|
||||
Reference in New Issue
Block a user