test: Migrate 1-workflows to Playwright (#17360)

This commit is contained in:
shortstacked
2025-08-01 10:27:48 +01:00
committed by GitHub
parent 38cef9d133
commit b99b93a637
19 changed files with 1248 additions and 68 deletions

View File

@@ -1,11 +1,151 @@
import { test, expect } from '../fixtures/base';
// Example of importing a workflow from a file
const NOTIFICATIONS = {
CREATED: 'Workflow successfully created',
ARCHIVED: 'archived',
UNARCHIVED: 'unarchived',
DELETED: 'deleted',
};
test.describe('Workflows', () => {
test('should create a new workflow using empty state card @db:reset', async ({ n8n }) => {
test.beforeEach(async ({ n8n }) => {
await n8n.goHome();
});
test('should create a new workflow using empty state card @db:reset', async ({ n8n }) => {
await n8n.workflows.clickNewWorkflowCard();
await n8n.workflows.importWorkflow('Test_workflow_1.json', 'Empty State Card Workflow');
await expect(n8n.workflows.workflowTags()).toHaveText(['some-tag-1', 'some-tag-2']);
await n8n.canvas.importWorkflow('Test_workflow_1.json', 'Empty State Card Workflow');
await expect(n8n.canvas.getWorkflowTags()).toHaveText(['some-tag-1', 'some-tag-2']);
});
test('should create a new workflow using add workflow button', async ({ n8n }) => {
await n8n.workflows.clickAddWorkflowButton();
const workflowName = `Test Workflow ${Date.now()}`;
await n8n.canvas.setWorkflowName(workflowName);
await n8n.canvas.clickSaveWorkflowButton();
await expect(
n8n.notifications.notificationContainerByText(NOTIFICATIONS.CREATED),
).toBeVisible();
});
test('should search for workflows', async ({ n8n }) => {
const date = Date.now();
const specificName = `Specific Test ${date}`;
const genericName = `Generic Test ${date}`;
await n8n.workflowComposer.createWorkflow(specificName);
await n8n.goHome();
await n8n.workflowComposer.createWorkflow(genericName);
await n8n.goHome();
// Search for specific workflow
await n8n.workflows.searchWorkflows(specificName);
await expect(n8n.workflows.getWorkflowItems()).toHaveCount(1);
await expect(n8n.workflows.getWorkflowByName(specificName)).toBeVisible();
// Search with partial term
await n8n.workflows.clearSearch();
await n8n.workflows.searchWorkflows(date.toString());
await expect(n8n.workflows.getWorkflowItems()).toHaveCount(2);
// Search for non-existent
await n8n.workflows.clearSearch();
await n8n.workflows.searchWorkflows('NonExistentWorkflow123');
await expect(n8n.workflows.getWorkflowItems()).toHaveCount(0);
await expect(n8n.page.getByText('No workflows found')).toBeVisible();
});
test('should archive and unarchive a workflow', async ({ n8n }) => {
const workflowName = `Archive Test ${Date.now()}`;
await n8n.workflowComposer.createWorkflow(workflowName);
await n8n.goHome();
// Create a second workflow so we can still see filters
await n8n.workflowComposer.createWorkflow();
await n8n.goHome();
const workflow = n8n.workflows.getWorkflowByName(workflowName);
await n8n.workflows.archiveWorkflow(workflow);
await expect(
n8n.notifications.notificationContainerByText(NOTIFICATIONS.ARCHIVED),
).toBeVisible();
await expect(workflow).toBeHidden();
await n8n.workflows.toggleShowArchived();
await expect(workflow).toBeVisible();
await n8n.workflows.unarchiveWorkflow(workflow);
await expect(
n8n.notifications.notificationContainerByText(NOTIFICATIONS.UNARCHIVED),
).toBeVisible();
});
test('should delete an archived workflow', async ({ n8n }) => {
const workflowName = `Delete Test ${Date.now()}`;
await n8n.workflowComposer.createWorkflow(workflowName);
await n8n.goHome();
await n8n.workflowComposer.createWorkflow();
await n8n.goHome();
const workflow = n8n.workflows.getWorkflowByName(workflowName);
await n8n.workflows.archiveWorkflow(workflow);
await expect(
n8n.notifications.notificationContainerByText(NOTIFICATIONS.ARCHIVED),
).toBeVisible();
await n8n.workflows.toggleShowArchived();
await n8n.workflows.deleteWorkflow(workflow);
await expect(
n8n.notifications.notificationContainerByText(NOTIFICATIONS.DELETED),
).toBeVisible();
await expect(workflow).toBeHidden();
});
test('should filter workflows by tag @db:reset', async ({ n8n }) => {
const taggedWorkflow =
await n8n.workflowComposer.createWorkflowFromJsonFile('Test_workflow_1.json');
await n8n.workflowComposer.createWorkflowFromJsonFile('Test_workflow_2.json');
await n8n.goHome();
await n8n.workflows.filterByTag('some-tag-1');
await expect(n8n.workflows.getWorkflowByName(taggedWorkflow.workflowName)).toBeVisible();
});
test('should preserve search and filters in URL @db:reset', async ({ n8n }) => {
const date = Date.now();
await n8n.workflowComposer.createWorkflowFromJsonFile(
'Test_workflow_2.json',
`My Tagged Workflow ${date}`,
);
await n8n.goHome();
// Apply search
await n8n.workflows.searchWorkflows('Tagged');
// Apply tag filter
await n8n.workflows.filterByTag('other-tag-1');
// Verify URL contains filters
await expect(n8n.page).toHaveURL(/search=Tagged/);
// Reload and verify filters persist
await n8n.page.reload();
await expect(n8n.workflows.getSearchBar()).toHaveValue('Tagged');
await expect(n8n.workflows.getWorkflowByName(`My Tagged Workflow ${date}`)).toBeVisible();
});
test('should share a workflow', async ({ n8n }) => {
const workflowName = `Share Test ${Date.now()}`;
await n8n.workflowComposer.createWorkflow(workflowName);
await n8n.goHome();
await n8n.workflows.shareWorkflow(workflowName);
await expect(n8n.workflowSharingModal.getModal()).toBeVisible();
});
});

View File

@@ -1,4 +1,5 @@
import { test, expect } from '../fixtures/base';
import type { n8nPage } from '../pages/n8nPage';
// Example of using helper functions inside a test
test.describe('Debug mode', () => {
@@ -22,8 +23,8 @@ test.describe('Debug mode', () => {
});
// Helper function to create basic workflow
async function createBasicWorkflow(n8n, url = URLS.FAILING) {
await n8n.workflows.clickAddWorklowButton();
async function createBasicWorkflow(n8n: n8nPage, url = URLS.FAILING) {
await n8n.workflows.clickAddWorkflowButton();
await n8n.canvas.addNode('Manual Trigger');
await n8n.canvas.addNode('HTTP Request');
await n8n.ndv.fillParameterInput('URL', url);
@@ -33,7 +34,7 @@ test.describe('Debug mode', () => {
}
// Helper function to import execution for debugging
async function importExecutionForDebugging(n8n) {
async function importExecutionForDebugging(n8n: n8nPage) {
await n8n.canvas.clickExecutionsTab();
await n8n.executions.clickDebugInEditorButton();
await n8n.notifications.waitForNotificationAndClose(NOTIFICATIONS.EXECUTION_IMPORTED);
@@ -105,7 +106,7 @@ test.describe('Debug mode', () => {
expect(n8n.page.url()).toContain('/debug');
});
async function attemptCopyToEditor(n8n) {
async function attemptCopyToEditor(n8n: n8nPage) {
await n8n.canvas.clickExecutionsTab();
await n8n.executions.clickLastExecutionItem();
await n8n.executions.clickCopyToEditorButton();

View File

@@ -85,7 +85,7 @@ test.describe('Projects @db:reset', () => {
await subn8n.canvas.saveWorkflow();
await subn8n.page.goto('/home/workflows');
await subn8n.projectWorkflows.clickProjectMenuItem(projectName);
await subn8n.sideBar.clickProjectMenuItem(projectName);
await subn8n.page.getByRole('link', { name: 'Workflows' }).click();
// Get Workflow Count

View File

@@ -5,8 +5,8 @@ test.describe('PDF Test', () => {
// eslint-disable-next-line playwright/no-skipped-test
test.skip('Can read and write PDF files and extract text', async ({ n8n }) => {
await n8n.goHome();
await n8n.workflows.clickAddWorklowButton();
await n8n.workflows.importWorkflow('test_pdf_workflow.json', 'PDF Workflow');
await n8n.workflows.clickAddWorkflowButton();
await n8n.canvas.importWorkflow('test_pdf_workflow.json', 'PDF Workflow');
await n8n.canvas.clickExecuteWorkflowButton();
await expect(
n8n.notifications.notificationContainerByText('Workflow executed successfully'),