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,67 @@
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Node Creator Actions', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
});
|
||||
|
||||
test('should add node to canvas from actions panel', async ({ n8n }) => {
|
||||
const editImageNode = 'Edit Image';
|
||||
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor(editImageNode);
|
||||
await n8n.canvas.nodeCreator.selectItem(editImageNode);
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getActiveSubcategory()).toContainText(editImageNode);
|
||||
await n8n.canvas.nodeCreator.selectItem('Crop Image');
|
||||
await expect(n8n.ndv.getContainer()).toBeVisible();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
});
|
||||
|
||||
test('should search through actions and confirm added action', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('ftp');
|
||||
await n8n.canvas.nodeCreator.selectItem('FTP');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getActiveSubcategory()).toContainText('FTP');
|
||||
await n8n.canvas.nodeCreator.clearSearch();
|
||||
await n8n.canvas.nodeCreator.searchFor('rename');
|
||||
await n8n.canvas.nodeCreator.selectItem('Rename');
|
||||
|
||||
await expect(n8n.ndv.getContainer()).toBeVisible();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
});
|
||||
|
||||
test('should show multiple actions for multi-action nodes', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('OpenWeatherMap');
|
||||
await n8n.canvas.nodeCreator.selectItem('OpenWeatherMap');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getActiveSubcategory()).toContainText('OpenWeatherMap');
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems().first()).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems().nth(1)).toBeVisible();
|
||||
|
||||
await n8n.canvas.nodeCreator.getNodeItems().first().click();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
});
|
||||
|
||||
test('should add node with specific operation configuration', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('Slack');
|
||||
await n8n.canvas.nodeCreator.selectItem('Slack');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getActiveSubcategory()).toContainText('Slack');
|
||||
await n8n.canvas.nodeCreator.getNodeItems().first().click();
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,105 @@
|
||||
import { MANUAL_TRIGGER_NODE_DISPLAY_NAME } from '../../../config/constants';
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Node Creator Categories', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
});
|
||||
|
||||
test('should have "Actions" section collapsed when opening actions view from Trigger root view', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('ActiveCampaign');
|
||||
await n8n.canvas.nodeCreator.selectItem('ActiveCampaign');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Actions')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Triggers')).toBeVisible();
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Triggers').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'false',
|
||||
);
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Actions').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'true',
|
||||
);
|
||||
|
||||
await n8n.canvas.nodeCreator.selectCategoryItem('Actions');
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Actions').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'false',
|
||||
);
|
||||
});
|
||||
|
||||
test('should have "Triggers" section collapsed when opening actions view from Regular root view', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
await n8n.canvas.addNode('Manual Trigger');
|
||||
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.nodeCreator.searchFor('n8n');
|
||||
await n8n.canvas.nodeCreator.getNodeItems().filter({ hasText: 'n8n' }).first().click();
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Actions').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'false',
|
||||
);
|
||||
|
||||
await n8n.canvas.nodeCreator.selectCategoryItem('Actions');
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Actions').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'true',
|
||||
);
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Triggers').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'true',
|
||||
);
|
||||
|
||||
await n8n.canvas.nodeCreator.selectCategoryItem('Triggers');
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Triggers').locator('..')).toHaveAttribute(
|
||||
'data-category-collapsed',
|
||||
'false',
|
||||
);
|
||||
});
|
||||
|
||||
test('should show callout and two suggested nodes if node has no trigger actions', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('Customer Datastore (n8n training)');
|
||||
await n8n.canvas.nodeCreator.selectItem('Customer Datastore (n8n training)');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getNoTriggersCallout()).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getItem('On a Schedule')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getItem('On a Webhook call')).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show intro callout if user has not made a production execution', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('Customer Datastore (n8n training)');
|
||||
await n8n.canvas.nodeCreator.selectItem('Customer Datastore (n8n training)');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getActivationCallout()).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show Trigger and Actions sections during search', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('Customer Datastore (n8n training)');
|
||||
await n8n.canvas.nodeCreator.selectItem('Customer Datastore (n8n training)');
|
||||
|
||||
await n8n.canvas.nodeCreator.searchFor('Non existent action name');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Triggers')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getCategoryItem('Actions')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getNoTriggersCallout()).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getItem('On a Schedule')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getItem('On a Webhook call')).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
import { MANUAL_TRIGGER_NODE_DISPLAY_NAME } from '../../../config/constants';
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Node Creator Navigation', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
});
|
||||
|
||||
test('should open node creator on trigger tab if no trigger is on canvas', async ({ n8n }) => {
|
||||
await n8n.canvas.clickCanvasPlusButton();
|
||||
await expect(n8n.canvas.nodeCreator.getRoot()).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getTriggerText()).toBeVisible();
|
||||
});
|
||||
|
||||
test('should navigate subcategory and return', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
|
||||
await n8n.canvas.nodeCreator.navigateToSubcategory('On app event');
|
||||
await expect(n8n.canvas.nodeCreator.getActiveSubcategory()).toContainText('On app event');
|
||||
|
||||
await n8n.canvas.nodeCreator.goBackFromSubcategory();
|
||||
await expect(n8n.canvas.nodeCreator.getActiveSubcategory()).not.toContainText('On app event');
|
||||
});
|
||||
|
||||
test('should search for nodes with various queries', async ({ n8n }) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
|
||||
await n8n.canvas.nodeCreator.searchFor('manual');
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems()).toHaveCount(1);
|
||||
|
||||
await n8n.canvas.nodeCreator.clearSearch();
|
||||
await n8n.canvas.nodeCreator.searchFor('manual123');
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems()).toHaveCount(0);
|
||||
await expect(n8n.canvas.nodeCreator.getNoResults()).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getNoResults()).toContainText("We didn't make that... yet");
|
||||
|
||||
await n8n.canvas.nodeCreator.clearSearch();
|
||||
await n8n.canvas.nodeCreator.searchFor('edit image');
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems()).toHaveCount(1);
|
||||
|
||||
await n8n.canvas.nodeCreator.clearSearch();
|
||||
await n8n.canvas.nodeCreator.searchFor('this node totally does not exist');
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems()).toHaveCount(0);
|
||||
|
||||
await n8n.canvas.nodeCreator.clearSearch();
|
||||
await n8n.canvas.nodeCreator.navigateToSubcategory('On app event');
|
||||
|
||||
await n8n.canvas.nodeCreator.searchFor('edit image');
|
||||
await expect(
|
||||
n8n.canvas.nodeCreator.getCategoryItem('Results in other categories'),
|
||||
).toBeVisible();
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems()).toHaveCount(1);
|
||||
await expect(n8n.canvas.nodeCreator.getItem('Edit Image')).toBeVisible();
|
||||
|
||||
await n8n.canvas.nodeCreator.clearSearch();
|
||||
await n8n.canvas.nodeCreator.searchFor('edit image123123');
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems()).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('should check correct view panels after adding manual trigger', async ({ n8n }) => {
|
||||
await n8n.canvas.clickCanvasPlusButton();
|
||||
await expect(n8n.canvas.nodeCreator.getTriggerText()).toBeVisible();
|
||||
await n8n.canvas.nodeCreator.close();
|
||||
|
||||
await n8n.canvas.addNode('Manual Trigger');
|
||||
await expect(n8n.canvas.getCanvasPlusButton()).toBeHidden();
|
||||
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await expect(n8n.canvas.nodeCreator.getNextText()).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
import { MANUAL_TRIGGER_NODE_DISPLAY_NAME } from '../../../config/constants';
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Node Creator Special Nodes', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
});
|
||||
|
||||
test('should correctly append a No Op node when Loop Over Items node is added (from add button)', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
await n8n.canvas.nodeCreator.open();
|
||||
await n8n.canvas.nodeCreator.searchFor('Loop Over Items');
|
||||
await n8n.canvas.nodeCreator.selectItem('Loop Over Items');
|
||||
await n8n.ndv.close();
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(3);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(3);
|
||||
await expect(n8n.canvas.nodeByName('Loop Over Items')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeByName('Replace Me')).toBeVisible();
|
||||
});
|
||||
|
||||
test('should correctly append a No Op node when Loop Over Items node is added (from connection)', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
await n8n.canvas.addNode('Manual Trigger');
|
||||
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.nodeCreator.searchFor('Loop Over Items');
|
||||
await n8n.canvas.nodeCreator.selectItem('Loop Over Items');
|
||||
await n8n.ndv.close();
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(3);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(3);
|
||||
await expect(n8n.canvas.nodeByName('Loop Over Items')).toBeVisible();
|
||||
await expect(n8n.canvas.nodeByName('Replace Me')).toBeVisible();
|
||||
});
|
||||
|
||||
test('should add a Send and Wait for Response node', async ({ n8n }) => {
|
||||
await n8n.canvas.addNode('Manual Trigger');
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
|
||||
await n8n.canvas.nodeCreator.navigateToSubcategory('Human review');
|
||||
await n8n.canvas.nodeCreator.selectItem('Slack');
|
||||
await n8n.ndv.setupHelper.setParameter('operation', 'Send and Wait for Response');
|
||||
await n8n.ndv.close();
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { MANUAL_TRIGGER_NODE_DISPLAY_NAME } from '../../../config/constants';
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Node Creator Vector Stores', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
await n8n.canvas.addNode('Manual Trigger');
|
||||
});
|
||||
|
||||
test('should show vector stores actions', async ({ n8n }) => {
|
||||
const expectedActions = [
|
||||
'Get ranked documents from vector store',
|
||||
'Add documents to vector store',
|
||||
'Retrieve documents for Chain/Tool as Vector Store',
|
||||
'Retrieve documents for AI Agent as Tool',
|
||||
];
|
||||
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.nodeCreator.searchFor('Vector Store');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems().first()).toBeVisible();
|
||||
|
||||
await n8n.canvas.nodeCreator.getItem('Simple Vector Store').click();
|
||||
|
||||
for (const action of expectedActions) {
|
||||
await expect(n8n.canvas.nodeCreator.getItem(action)).toBeVisible();
|
||||
}
|
||||
|
||||
await n8n.canvas.nodeCreator.goBackFromSubcategory();
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems().first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('should find vector store nodes in creator', async ({ n8n }) => {
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.nodeCreator.searchFor('Vector Store');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getNodeItems().first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('should search for specific vector store nodes', async ({ n8n }) => {
|
||||
await n8n.canvas.clickNodePlusEndpoint(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
|
||||
await n8n.canvas.nodeCreator.searchFor('Simple Vector Store');
|
||||
|
||||
await expect(n8n.canvas.nodeCreator.getItem('Simple Vector Store')).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
|
||||
test.describe('Node Creator Workflow Building', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ n8n }) => {
|
||||
await n8n.start.fromBlankCanvas();
|
||||
});
|
||||
|
||||
test('should append manual trigger when adding action node from canvas add button', async ({
|
||||
n8n,
|
||||
}) => {
|
||||
await n8n.canvas.clickCanvasPlusButton();
|
||||
await n8n.canvas.nodeCreator.searchFor('n8n');
|
||||
await n8n.canvas.nodeCreator.selectItem('n8n');
|
||||
await n8n.canvas.nodeCreator.selectCategoryItem('Actions');
|
||||
await n8n.canvas.nodeCreator.selectItem('Create a credential');
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
await expect(n8n.canvas.nodeConnections()).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('should append manual trigger when adding action node from plus button', async ({ n8n }) => {
|
||||
await n8n.canvas.clickCanvasPlusButton();
|
||||
await n8n.canvas.nodeCreator.searchFor('n8n');
|
||||
await n8n.canvas.nodeCreator.selectItem('n8n');
|
||||
await n8n.canvas.nodeCreator.selectCategoryItem('Actions');
|
||||
await n8n.canvas.nodeCreator.selectItem('Create a credential');
|
||||
await n8n.page.keyboard.press('Escape');
|
||||
|
||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user