mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
test: Migrate small Cypress tests to Playwright (#18922)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,34 +0,0 @@
|
|||||||
import { NDV, WorkflowPage } from '../pages';
|
|
||||||
import { clearNotifications } from '../pages/notifications';
|
|
||||||
|
|
||||||
const workflowPage = new WorkflowPage();
|
|
||||||
const ndv = new NDV();
|
|
||||||
|
|
||||||
describe('ADO-2230 NDV Pagination Reset', () => {
|
|
||||||
it('should reset pagaintion if data size changes to less than current page', () => {
|
|
||||||
// setup, load workflow with debughelper node with random seed
|
|
||||||
workflowPage.actions.visit();
|
|
||||||
cy.createFixtureWorkflow('NDV-debug-generate-data.json', 'Debug workflow');
|
|
||||||
workflowPage.actions.openNode('DebugHelper');
|
|
||||||
|
|
||||||
// execute node outputting 10 pages, check output of first page
|
|
||||||
ndv.actions.execute();
|
|
||||||
clearNotifications();
|
|
||||||
ndv.getters.outputTbodyCell(1, 1).invoke('text').should('eq', 'Terry.Dach@hotmail.com');
|
|
||||||
|
|
||||||
// open 4th page, check output
|
|
||||||
ndv.getters.pagination().should('be.visible');
|
|
||||||
ndv.getters.pagination().find('li.number').should('have.length', 5);
|
|
||||||
ndv.getters.pagination().find('li.number').eq(3).click();
|
|
||||||
ndv.getters.outputTbodyCell(1, 1).invoke('text').should('eq', 'Shane.Cormier68@yahoo.com');
|
|
||||||
|
|
||||||
// output a lot less data
|
|
||||||
ndv.getters.parameterInput('randomDataCount').find('input').clear().type('20');
|
|
||||||
ndv.actions.execute();
|
|
||||||
clearNotifications();
|
|
||||||
|
|
||||||
// check we are back to second page now
|
|
||||||
ndv.getters.pagination().find('li.number').should('have.length', 2);
|
|
||||||
ndv.getters.outputTbodyCell(1, 1).invoke('text').should('eq', 'Sylvia.Weber@hotmail.com');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { getOutputTableRow } from '../composables/ndv';
|
|
||||||
import { getCanvasNodes, openNode } from '../composables/workflow';
|
|
||||||
import SIMPLE_WORKFLOW from '../fixtures/Manual_wait_set.json';
|
|
||||||
import WORKFLOW_WITH_PINNED from '../fixtures/Webhook_set_pinned.json';
|
|
||||||
import { importWorkflow, visitDemoPage } from '../pages/demo';
|
|
||||||
import { errorToast } from '../pages/notifications';
|
|
||||||
|
|
||||||
describe('Demo', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.overrideSettings({ previewMode: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can import template', () => {
|
|
||||||
visitDemoPage();
|
|
||||||
errorToast().should('not.exist');
|
|
||||||
importWorkflow(SIMPLE_WORKFLOW);
|
|
||||||
getCanvasNodes().should('have.length', 3);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can import workflow with pin data', () => {
|
|
||||||
visitDemoPage();
|
|
||||||
importWorkflow(WORKFLOW_WITH_PINNED);
|
|
||||||
getCanvasNodes().should('have.length', 2);
|
|
||||||
openNode('Webhook');
|
|
||||||
getOutputTableRow(0).should('include.text', 'headers');
|
|
||||||
getOutputTableRow(1).should('include.text', 'dragons');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can override theme to dark', () => {
|
|
||||||
visitDemoPage('dark');
|
|
||||||
cy.get('body').should('have.attr', 'data-theme', 'dark');
|
|
||||||
errorToast().should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can override theme to light', () => {
|
|
||||||
visitDemoPage('light');
|
|
||||||
cy.get('body').should('have.attr', 'data-theme', 'light');
|
|
||||||
errorToast().should('not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import { WorkerViewPage } from '../pages';
|
|
||||||
|
|
||||||
const workerViewPage = new WorkerViewPage();
|
|
||||||
|
|
||||||
describe('Worker View (unlicensed)', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.disableFeature('workerView');
|
|
||||||
cy.disableQueueMode();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not show up in the menu sidebar', () => {
|
|
||||||
cy.signinAsMember(0);
|
|
||||||
cy.visit(workerViewPage.url);
|
|
||||||
workerViewPage.getters.menuItem().should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show action box', () => {
|
|
||||||
cy.signinAsMember(0);
|
|
||||||
cy.visit(workerViewPage.url);
|
|
||||||
workerViewPage.getters.workerViewUnlicensed().should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Worker View (licensed)', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.enableFeature('workerView');
|
|
||||||
cy.enableQueueMode();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show up in the menu sidebar', () => {
|
|
||||||
cy.signinAsOwner();
|
|
||||||
cy.enableQueueMode();
|
|
||||||
cy.visit(workerViewPage.url);
|
|
||||||
workerViewPage.getters.menuItem().should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show worker list view', () => {
|
|
||||||
cy.signinAsMember(0);
|
|
||||||
cy.visit(workerViewPage.url);
|
|
||||||
workerViewPage.getters.workerViewLicensed().should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import {
|
|
||||||
closeVersionUpdatesPanel,
|
|
||||||
getVersionCard,
|
|
||||||
getVersionUpdatesPanelOpenButton,
|
|
||||||
openWhatsNewMenu,
|
|
||||||
openVersionUpdatesPanel,
|
|
||||||
} from '../composables/versions';
|
|
||||||
import { WorkflowsPage } from '../pages/workflows';
|
|
||||||
|
|
||||||
const workflowsPage = new WorkflowsPage();
|
|
||||||
|
|
||||||
describe('Versions', () => {
|
|
||||||
it('should open updates panel', () => {
|
|
||||||
cy.overrideSettings({
|
|
||||||
releaseChannel: 'stable',
|
|
||||||
versionCli: '1.0.0',
|
|
||||||
versionNotifications: {
|
|
||||||
enabled: true,
|
|
||||||
endpoint: 'https://api.n8n.io/api/versions/',
|
|
||||||
whatsNewEnabled: true,
|
|
||||||
whatsNewEndpoint: 'https://api.n8n.io/api/whats-new',
|
|
||||||
infoUrl: 'https://docs.n8n.io/getting-started/installation/updating.html',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.visit(workflowsPage.url);
|
|
||||||
cy.wait('@loadSettings');
|
|
||||||
|
|
||||||
openWhatsNewMenu();
|
|
||||||
getVersionUpdatesPanelOpenButton().should('contain', '2 versions behind');
|
|
||||||
openVersionUpdatesPanel();
|
|
||||||
getVersionCard().should('have.length', 2);
|
|
||||||
closeVersionUpdatesPanel();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import {
|
|
||||||
getBecomeTemplateCreatorCta,
|
|
||||||
getCloseBecomeTemplateCreatorCtaButton,
|
|
||||||
interceptCtaRequestWithResponse,
|
|
||||||
} from '../composables/becomeTemplateCreatorCta';
|
|
||||||
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
|
|
||||||
|
|
||||||
const WorkflowsPage = new WorkflowsPageClass();
|
|
||||||
|
|
||||||
// Migrated to Playwright
|
|
||||||
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
|
|
||||||
describe.skip('Become creator CTA', () => {
|
|
||||||
it('should not show the CTA if user is not eligible', () => {
|
|
||||||
interceptCtaRequestWithResponse(false).as('cta');
|
|
||||||
cy.visit(WorkflowsPage.url);
|
|
||||||
|
|
||||||
cy.wait('@cta');
|
|
||||||
|
|
||||||
getBecomeTemplateCreatorCta().should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show the CTA if the user is eligible', () => {
|
|
||||||
interceptCtaRequestWithResponse(true).as('cta');
|
|
||||||
cy.visit(WorkflowsPage.url);
|
|
||||||
|
|
||||||
cy.wait('@cta');
|
|
||||||
|
|
||||||
getBecomeTemplateCreatorCta().should('be.visible');
|
|
||||||
|
|
||||||
getCloseBecomeTemplateCreatorCtaButton().click();
|
|
||||||
|
|
||||||
getBecomeTemplateCreatorCta().should('not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
31
packages/testing/playwright/pages/DemoPage.ts
Normal file
31
packages/testing/playwright/pages/DemoPage.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { BasePage } from './BasePage';
|
||||||
|
|
||||||
|
export class DemoPage extends BasePage {
|
||||||
|
async visitDemoPage(theme?: 'dark' | 'light') {
|
||||||
|
const query = theme ? `?theme=${theme}` : '';
|
||||||
|
await this.page.goto('/workflows/demo' + query);
|
||||||
|
await this.getBody().waitFor({ state: 'visible' });
|
||||||
|
// eslint-disable-next-line playwright/no-networkidle
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
await this.page.evaluate(() => {
|
||||||
|
// @ts-expect-error - this is a custom property added by the demo page
|
||||||
|
window.preventNodeViewBeforeUnload = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import a workflow into the demo page
|
||||||
|
* @param workflow - The workflow to import
|
||||||
|
*/
|
||||||
|
async importWorkflow(workflow: object) {
|
||||||
|
const OPEN_WORKFLOW = { command: 'openWorkflow', workflow };
|
||||||
|
await this.page.evaluate((message) => {
|
||||||
|
console.log('Posting message:', JSON.stringify(message));
|
||||||
|
window.postMessage(JSON.stringify(message), '*');
|
||||||
|
}, OPEN_WORKFLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBody() {
|
||||||
|
return this.page.locator('body');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -552,4 +552,39 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
// eslint-disable-next-line playwright/no-wait-for-timeout
|
// eslint-disable-next-line playwright/no-wait-for-timeout
|
||||||
await this.page.waitForTimeout(2500);
|
await this.page.waitForTimeout(2500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pagination methods for output panel
|
||||||
|
getOutputPagination() {
|
||||||
|
return this.getOutputPanel().getByTestId('ndv-data-pagination');
|
||||||
|
}
|
||||||
|
|
||||||
|
getOutputPaginationPages() {
|
||||||
|
return this.getOutputPagination().locator('.el-pager li.number');
|
||||||
|
}
|
||||||
|
|
||||||
|
async navigateToOutputPage(pageNumber: number): Promise<void> {
|
||||||
|
const pages = this.getOutputPaginationPages();
|
||||||
|
await pages.nth(pageNumber - 1).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCurrentOutputPage(): Promise<number> {
|
||||||
|
const activePage = this.getOutputPagination().locator('.el-pager li.is-active').first();
|
||||||
|
const pageText = await activePage.textContent();
|
||||||
|
return parseInt(pageText ?? '1', 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getOutputPageContent(row: number = 0, col: number = 0): Promise<string> {
|
||||||
|
return (await this.getOutputTbodyCell(row, col).textContent()) ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameter input value by clearing and filling (for parameters without standard test-id)
|
||||||
|
* @param parameterName - The parameter name
|
||||||
|
* @param value - The value to set
|
||||||
|
*/
|
||||||
|
async setParameterInputValue(parameterName: string, value: string): Promise<void> {
|
||||||
|
const input = this.getParameterInput(parameterName).locator('input');
|
||||||
|
await input.clear();
|
||||||
|
await input.fill(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ export class SettingsPage extends BasePage {
|
|||||||
return this.page.getByTestId('menu-item').getByTestId(id);
|
return this.page.getByTestId('menu-item').getByTestId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMenuItemByText(text: string) {
|
||||||
|
return this.page.getByTestId('menu-item').getByText(text, { exact: true });
|
||||||
|
}
|
||||||
|
|
||||||
async goToSettings() {
|
async goToSettings() {
|
||||||
await this.page.goto('/settings');
|
await this.page.goto('/settings');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export class VersionsPage extends BasePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getWhatsNewMenuItem() {
|
getWhatsNewMenuItem() {
|
||||||
return this.page.getByTestId('menu-item').getByTestId('whats-new');
|
return this.page.getByText('What’s New');
|
||||||
}
|
}
|
||||||
|
|
||||||
async openWhatsNewMenu() {
|
async openWhatsNewMenu() {
|
||||||
|
|||||||
27
packages/testing/playwright/pages/WorkerViewPage.ts
Normal file
27
packages/testing/playwright/pages/WorkerViewPage.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { BasePage } from './BasePage';
|
||||||
|
|
||||||
|
export class WorkerViewPage extends BasePage {
|
||||||
|
getWorkerCards() {
|
||||||
|
return this.page.getByTestId('worker-card');
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorkerCard(workerId: string) {
|
||||||
|
return this.getWorkerCards().filter({ hasText: workerId });
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorkerViewLicensed() {
|
||||||
|
return this.page.getByTestId('worker-view-licensed');
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorkerViewUnlicensed() {
|
||||||
|
return this.page.getByTestId('worker-view-unlicensed');
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorkerMenuItem() {
|
||||||
|
return this.page.getByTestId('menu-item').getByText('Workers', { exact: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
async visitWorkerView() {
|
||||||
|
await this.page.goto('/settings/workers');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { AIAssistantPage } from './AIAssistantPage';
|
|||||||
import { BecomeCreatorCTAPage } from './BecomeCreatorCTAPage';
|
import { BecomeCreatorCTAPage } from './BecomeCreatorCTAPage';
|
||||||
import { CanvasPage } from './CanvasPage';
|
import { CanvasPage } from './CanvasPage';
|
||||||
import { CredentialsPage } from './CredentialsPage';
|
import { CredentialsPage } from './CredentialsPage';
|
||||||
|
import { DemoPage } from './DemoPage';
|
||||||
import { ExecutionsPage } from './ExecutionsPage';
|
import { ExecutionsPage } from './ExecutionsPage';
|
||||||
import { IframePage } from './IframePage';
|
import { IframePage } from './IframePage';
|
||||||
import { InteractionsPage } from './InteractionsPage';
|
import { InteractionsPage } from './InteractionsPage';
|
||||||
@@ -14,6 +15,7 @@ import { ProjectSettingsPage } from './ProjectSettingsPage';
|
|||||||
import { SettingsPage } from './SettingsPage';
|
import { SettingsPage } from './SettingsPage';
|
||||||
import { SidebarPage } from './SidebarPage';
|
import { SidebarPage } from './SidebarPage';
|
||||||
import { VersionsPage } from './VersionsPage';
|
import { VersionsPage } from './VersionsPage';
|
||||||
|
import { WorkerViewPage } from './WorkerViewPage';
|
||||||
import { WorkflowActivationModal } from './WorkflowActivationModal';
|
import { WorkflowActivationModal } from './WorkflowActivationModal';
|
||||||
import { WorkflowSettingsModal } from './WorkflowSettingsModal';
|
import { WorkflowSettingsModal } from './WorkflowSettingsModal';
|
||||||
import { WorkflowSharingModal } from './WorkflowSharingModal';
|
import { WorkflowSharingModal } from './WorkflowSharingModal';
|
||||||
@@ -33,7 +35,7 @@ export class n8nPage {
|
|||||||
readonly aiAssistant: AIAssistantPage;
|
readonly aiAssistant: AIAssistantPage;
|
||||||
readonly becomeCreatorCTA: BecomeCreatorCTAPage;
|
readonly becomeCreatorCTA: BecomeCreatorCTAPage;
|
||||||
readonly canvas: CanvasPage;
|
readonly canvas: CanvasPage;
|
||||||
|
readonly demo: DemoPage;
|
||||||
readonly iframe: IframePage;
|
readonly iframe: IframePage;
|
||||||
readonly interactions: InteractionsPage;
|
readonly interactions: InteractionsPage;
|
||||||
readonly ndv: NodeDetailsViewPage;
|
readonly ndv: NodeDetailsViewPage;
|
||||||
@@ -41,6 +43,7 @@ export class n8nPage {
|
|||||||
readonly projectSettings: ProjectSettingsPage;
|
readonly projectSettings: ProjectSettingsPage;
|
||||||
readonly settings: SettingsPage;
|
readonly settings: SettingsPage;
|
||||||
readonly versions: VersionsPage;
|
readonly versions: VersionsPage;
|
||||||
|
readonly workerView: WorkerViewPage;
|
||||||
readonly workflows: WorkflowsPage;
|
readonly workflows: WorkflowsPage;
|
||||||
readonly notifications: NotificationsPage;
|
readonly notifications: NotificationsPage;
|
||||||
readonly credentials: CredentialsPage;
|
readonly credentials: CredentialsPage;
|
||||||
@@ -66,7 +69,7 @@ export class n8nPage {
|
|||||||
this.aiAssistant = new AIAssistantPage(page);
|
this.aiAssistant = new AIAssistantPage(page);
|
||||||
this.becomeCreatorCTA = new BecomeCreatorCTAPage(page);
|
this.becomeCreatorCTA = new BecomeCreatorCTAPage(page);
|
||||||
this.canvas = new CanvasPage(page);
|
this.canvas = new CanvasPage(page);
|
||||||
|
this.demo = new DemoPage(page);
|
||||||
this.iframe = new IframePage(page);
|
this.iframe = new IframePage(page);
|
||||||
this.interactions = new InteractionsPage(page);
|
this.interactions = new InteractionsPage(page);
|
||||||
this.ndv = new NodeDetailsViewPage(page);
|
this.ndv = new NodeDetailsViewPage(page);
|
||||||
@@ -74,6 +77,7 @@ export class n8nPage {
|
|||||||
this.projectSettings = new ProjectSettingsPage(page);
|
this.projectSettings = new ProjectSettingsPage(page);
|
||||||
this.settings = new SettingsPage(page);
|
this.settings = new SettingsPage(page);
|
||||||
this.versions = new VersionsPage(page);
|
this.versions = new VersionsPage(page);
|
||||||
|
this.workerView = new WorkerViewPage(page);
|
||||||
this.workflows = new WorkflowsPage(page);
|
this.workflows = new WorkflowsPage(page);
|
||||||
this.notifications = new NotificationsPage(page);
|
this.notifications = new NotificationsPage(page);
|
||||||
this.credentials = new CredentialsPage(page);
|
this.credentials = new CredentialsPage(page);
|
||||||
|
|||||||
@@ -59,11 +59,16 @@ export class WorkflowApiHelper {
|
|||||||
const webhookPrefix = options?.webhookPrefix ?? 'test-webhook';
|
const webhookPrefix = options?.webhookPrefix ?? 'test-webhook';
|
||||||
const uniqueSuffix = nanoid(idLength);
|
const uniqueSuffix = nanoid(idLength);
|
||||||
|
|
||||||
// Make workflow name unique
|
// Make workflow name unique; add a default if missing
|
||||||
if (workflow.name) {
|
if (workflow.name && workflow.name.trim().length > 0) {
|
||||||
workflow.name = `${workflow.name} (Test ${uniqueSuffix})`;
|
workflow.name = `${workflow.name} (Test ${uniqueSuffix})`;
|
||||||
|
} else {
|
||||||
|
workflow.name = `Test Workflow ${uniqueSuffix}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure workflow is inactive by default when not specified
|
||||||
|
workflow.active ??= false;
|
||||||
|
|
||||||
// Check if workflow has webhook nodes and process them
|
// Check if workflow has webhook nodes and process them
|
||||||
let webhookId: string | undefined;
|
let webhookId: string | undefined;
|
||||||
let webhookPath: string | undefined;
|
let webhookPath: string | undefined;
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { test, expect } from '../../fixtures/base';
|
||||||
|
|
||||||
|
test.describe('ADO-2230 NDV Pagination Reset', () => {
|
||||||
|
test('should reset pagination if data size changes to less than current page', async ({
|
||||||
|
n8n,
|
||||||
|
}) => {
|
||||||
|
await n8n.start.fromImportedWorkflow('NDV-debug-generate-data.json');
|
||||||
|
|
||||||
|
await n8n.canvas.openNode('DebugHelper');
|
||||||
|
await n8n.ndv.execute();
|
||||||
|
await n8n.notifications.quickCloseAll();
|
||||||
|
|
||||||
|
const outputPagination = n8n.ndv.getOutputPagination();
|
||||||
|
await expect(outputPagination).toBeVisible();
|
||||||
|
|
||||||
|
await expect(n8n.ndv.getOutputPaginationPages()).toHaveCount(5);
|
||||||
|
|
||||||
|
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).not.toBeEmpty();
|
||||||
|
const firstPageContent = await n8n.ndv.getOutputPageContent(0, 0);
|
||||||
|
|
||||||
|
await n8n.ndv.navigateToOutputPage(4);
|
||||||
|
|
||||||
|
const fourthPageContent = await n8n.ndv.getOutputPageContent(0, 0);
|
||||||
|
expect(fourthPageContent).not.toBe(firstPageContent);
|
||||||
|
|
||||||
|
await n8n.ndv.setParameterInputValue('randomDataCount', '20');
|
||||||
|
|
||||||
|
await n8n.ndv.execute();
|
||||||
|
await n8n.notifications.quickCloseAll();
|
||||||
|
|
||||||
|
await expect(n8n.ndv.getOutputPaginationPages()).toHaveCount(2);
|
||||||
|
|
||||||
|
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).not.toBeEmpty();
|
||||||
|
});
|
||||||
|
});
|
||||||
46
packages/testing/playwright/tests/ui/31-demo.spec.ts
Normal file
46
packages/testing/playwright/tests/ui/31-demo.spec.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { test, expect } from '../../fixtures/base';
|
||||||
|
import type { TestRequirements } from '../../Types';
|
||||||
|
import simpleWorkflow from '../../workflows/Manual_wait_set.json';
|
||||||
|
import workflowWithPinned from '../../workflows/Webhook_set_pinned.json';
|
||||||
|
|
||||||
|
const requirements: TestRequirements = {
|
||||||
|
config: {
|
||||||
|
settings: {
|
||||||
|
previewMode: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
test.describe('Demo', () => {
|
||||||
|
test.beforeEach(async ({ setupRequirements }) => {
|
||||||
|
await setupRequirements(requirements);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can import template', async ({ n8n }) => {
|
||||||
|
await n8n.demo.visitDemoPage();
|
||||||
|
expect(await n8n.notifications.getAllNotificationTexts()).toHaveLength(0);
|
||||||
|
await n8n.demo.importWorkflow(simpleWorkflow);
|
||||||
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can import workflow with pin data', async ({ n8n }) => {
|
||||||
|
await n8n.demo.visitDemoPage();
|
||||||
|
await n8n.demo.importWorkflow(workflowWithPinned);
|
||||||
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||||
|
await n8n.canvas.openNode('Webhook');
|
||||||
|
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('headers');
|
||||||
|
await expect(n8n.ndv.getOutputTableCell(1, 3)).toContainText('dragons');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can override theme to dark', async ({ n8n }) => {
|
||||||
|
await n8n.demo.visitDemoPage('dark');
|
||||||
|
await expect(n8n.demo.getBody()).toHaveAttribute('data-theme', 'dark');
|
||||||
|
expect(await n8n.notifications.getAllNotificationTexts()).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can override theme to light', async ({ n8n }) => {
|
||||||
|
await n8n.demo.visitDemoPage('light');
|
||||||
|
await expect(n8n.demo.getBody()).toHaveAttribute('data-theme', 'light');
|
||||||
|
expect(await n8n.notifications.getAllNotificationTexts()).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
39
packages/testing/playwright/tests/ui/32-worker-view.spec.ts
Normal file
39
packages/testing/playwright/tests/ui/32-worker-view.spec.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { test, expect } from '../../fixtures/base';
|
||||||
|
|
||||||
|
test.describe
|
||||||
|
.serial('Worker View', () => {
|
||||||
|
test.describe('unlicensed', () => {
|
||||||
|
test.beforeEach(async ({ api }) => {
|
||||||
|
await api.disableFeature('workerView');
|
||||||
|
await api.setQueueMode(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show up in the menu sidebar', async ({ n8n }) => {
|
||||||
|
await n8n.workerView.visitWorkerView();
|
||||||
|
await expect(n8n.workerView.getWorkerMenuItem()).toBeHidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show action box', async ({ n8n }) => {
|
||||||
|
await n8n.workerView.visitWorkerView();
|
||||||
|
await expect(n8n.workerView.getWorkerViewUnlicensed()).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('licensed', () => {
|
||||||
|
test.beforeEach(async ({ api }) => {
|
||||||
|
await api.enableFeature('workerView');
|
||||||
|
await api.setQueueMode(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show up in the menu sidebar', async ({ n8n }) => {
|
||||||
|
await n8n.goHome();
|
||||||
|
await n8n.workerView.visitWorkerView();
|
||||||
|
await expect(n8n.workerView.getWorkerMenuItem()).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show worker list view', async ({ n8n }) => {
|
||||||
|
await n8n.workerView.visitWorkerView();
|
||||||
|
await expect(n8n.workerView.getWorkerViewLicensed()).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
75
packages/testing/playwright/tests/ui/36-versions.spec.ts
Normal file
75
packages/testing/playwright/tests/ui/36-versions.spec.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import { test, expect } from '../../fixtures/base';
|
||||||
|
import type { TestRequirements } from '../../Types';
|
||||||
|
|
||||||
|
const requirements: TestRequirements = {
|
||||||
|
config: {
|
||||||
|
settings: {
|
||||||
|
releaseChannel: 'stable',
|
||||||
|
versionCli: '1.0.0',
|
||||||
|
versionNotifications: {
|
||||||
|
enabled: true,
|
||||||
|
endpoint: 'https://api.n8n.io/api/versions/',
|
||||||
|
whatsNewEnabled: true,
|
||||||
|
whatsNewEndpoint: 'https://api.n8n.io/api/whats-new',
|
||||||
|
infoUrl: 'https://docs.n8n.io/getting-started/installation/updating.html',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
intercepts: {
|
||||||
|
versions: {
|
||||||
|
url: '**/api/versions/**',
|
||||||
|
response: [
|
||||||
|
{
|
||||||
|
name: '1.0.0',
|
||||||
|
nodes: [],
|
||||||
|
createdAt: '2025-06-01T00:00:00Z',
|
||||||
|
description: 'Current version',
|
||||||
|
documentationUrl: 'https://docs.n8n.io',
|
||||||
|
hasBreakingChange: false,
|
||||||
|
hasSecurityFix: false,
|
||||||
|
hasSecurityIssue: false,
|
||||||
|
securityIssueFixVersion: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '1.0.1',
|
||||||
|
nodes: [],
|
||||||
|
createdAt: '2025-06-15T00:00:00Z',
|
||||||
|
description: 'Version 1.0.1',
|
||||||
|
documentationUrl: 'https://docs.n8n.io',
|
||||||
|
hasBreakingChange: false,
|
||||||
|
hasSecurityFix: false,
|
||||||
|
hasSecurityIssue: false,
|
||||||
|
securityIssueFixVersion: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '1.0.2',
|
||||||
|
nodes: [],
|
||||||
|
createdAt: '2025-06-30T00:00:00Z',
|
||||||
|
description: 'Version 1.0.2',
|
||||||
|
documentationUrl: 'https://docs.n8n.io',
|
||||||
|
hasBreakingChange: false,
|
||||||
|
hasSecurityFix: false,
|
||||||
|
hasSecurityIssue: false,
|
||||||
|
securityIssueFixVersion: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
test.describe('Versions', () => {
|
||||||
|
test('should open updates panel', async ({ n8n, setupRequirements }) => {
|
||||||
|
await setupRequirements(requirements);
|
||||||
|
await n8n.goHome();
|
||||||
|
await n8n.versions.openWhatsNewMenu();
|
||||||
|
await expect(n8n.versions.getVersionUpdatesPanelOpenButton()).toContainText(
|
||||||
|
'2 versions behind',
|
||||||
|
);
|
||||||
|
|
||||||
|
await n8n.versions.openVersionUpdatesPanel();
|
||||||
|
await expect(n8n.versions.getVersionCard()).toHaveCount(2);
|
||||||
|
|
||||||
|
await n8n.versions.closeVersionUpdatesPanel();
|
||||||
|
await expect(n8n.versions.getVersionUpdatesPanel()).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { test, expect } from '../../fixtures/base';
|
||||||
|
import type { TestRequirements } from '../../Types';
|
||||||
|
|
||||||
|
test.describe('Become creator CTA', () => {
|
||||||
|
test('should not show the CTA if user is not eligible', async ({ n8n, setupRequirements }) => {
|
||||||
|
const notEligibleRequirements: TestRequirements = {
|
||||||
|
intercepts: {
|
||||||
|
cta: {
|
||||||
|
url: '**/rest/cta/become-creator',
|
||||||
|
response: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await setupRequirements(notEligibleRequirements);
|
||||||
|
await n8n.goHome();
|
||||||
|
|
||||||
|
await expect(n8n.becomeCreatorCTA.getBecomeTemplateCreatorCta()).toBeHidden();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show the CTA if the user is eligible', async ({ n8n, setupRequirements }) => {
|
||||||
|
const eligibleRequirements: TestRequirements = {
|
||||||
|
intercepts: {
|
||||||
|
cta: {
|
||||||
|
url: '**/rest/cta/become-creator',
|
||||||
|
response: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await setupRequirements(eligibleRequirements);
|
||||||
|
await n8n.goHome();
|
||||||
|
|
||||||
|
await expect(n8n.becomeCreatorCTA.getBecomeTemplateCreatorCta()).toBeVisible();
|
||||||
|
|
||||||
|
await n8n.becomeCreatorCTA.closeBecomeTemplateCreatorCta();
|
||||||
|
|
||||||
|
await expect(n8n.becomeCreatorCTA.getBecomeTemplateCreatorCta()).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"templateCredsSetupCompleted": true,
|
||||||
|
"instanceId": "5b397bc122efafc165b2a6e67d5e8d75b8138f0d24d6352fac713e4845b002a6"
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"id": "df260de7-6f28-4d07-b7b5-29588e27335b",
|
||||||
|
"name": "When clicking \"Execute workflow\"",
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [780, 500]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"category": "randomData",
|
||||||
|
"randomDataSeed": "0",
|
||||||
|
"randomDataCount": 100
|
||||||
|
},
|
||||||
|
"id": "9e9a0708-86dc-474f-a60e-4315e757c08e",
|
||||||
|
"name": "DebugHelper",
|
||||||
|
"type": "n8n-nodes-base.debugHelper",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [1000, 500]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking \"Execute workflow\"": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "DebugHelper",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user