mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
test: Refactor page objects and reuse locators (#19191)
This commit is contained in:
@@ -139,7 +139,7 @@ function handleChangeOutputTableColumnCollapsing(columnName: string | null) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div ref="popOutContainer">
|
<div ref="popOutContainer" data-test-id="logs-panel">
|
||||||
<!-- force re-create with key for shortcuts to work in pop-out window -->
|
<!-- force re-create with key for shortcuts to work in pop-out window -->
|
||||||
<LogsViewKeyboardEventListener
|
<LogsViewKeyboardEventListener
|
||||||
:key="String(!!popOutWindow)"
|
:key="String(!!popOutWindow)"
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import { nanoid } from 'nanoid';
|
|||||||
import { BasePage } from './BasePage';
|
import { BasePage } from './BasePage';
|
||||||
import { ROUTES } from '../config/constants';
|
import { ROUTES } from '../config/constants';
|
||||||
import { resolveFromRoot } from '../utils/path-helper';
|
import { resolveFromRoot } from '../utils/path-helper';
|
||||||
|
import { LogsPanel } from './components/LogsPanel';
|
||||||
import { StickyComponent } from './components/StickyComponent';
|
import { StickyComponent } from './components/StickyComponent';
|
||||||
|
|
||||||
export class CanvasPage extends BasePage {
|
export class CanvasPage extends BasePage {
|
||||||
readonly sticky = new StickyComponent(this.page);
|
readonly sticky = new StickyComponent(this.page);
|
||||||
|
readonly logsPanel = new LogsPanel(this.page.getByTestId('logs-panel'));
|
||||||
|
|
||||||
saveWorkflowButton(): Locator {
|
saveWorkflowButton(): Locator {
|
||||||
return this.page.getByRole('button', { name: 'Save' });
|
return this.page.getByRole('button', { name: 'Save' });
|
||||||
@@ -535,22 +537,6 @@ export class CanvasPage extends BasePage {
|
|||||||
await this.clickContextMenuAction('execute');
|
await this.clickContextMenuAction('execute');
|
||||||
}
|
}
|
||||||
|
|
||||||
async clearExecutionData(): Promise<void> {
|
|
||||||
await this.page.getByTestId('clear-execution-data-button').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
getManualChatModal(): Locator {
|
|
||||||
return this.page.getByTestId('canvas-chat');
|
|
||||||
}
|
|
||||||
|
|
||||||
getManualChatInput(): Locator {
|
|
||||||
return this.getManualChatModal().locator('.chat-inputs textarea');
|
|
||||||
}
|
|
||||||
|
|
||||||
getManualChatMessages(): Locator {
|
|
||||||
return this.getManualChatModal().locator('.chat-messages-list .chat-message');
|
|
||||||
}
|
|
||||||
|
|
||||||
getNodesWithSpinner(): Locator {
|
getNodesWithSpinner(): Locator {
|
||||||
return this.page.getByTestId('canvas-node').filter({
|
return this.page.getByTestId('canvas-node').filter({
|
||||||
has: this.page.locator('[data-icon=refresh-cw]'),
|
has: this.page.locator('[data-icon=refresh-cw]'),
|
||||||
@@ -563,10 +549,6 @@ export class CanvasPage extends BasePage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendManualChatMessage(message: string): Promise<void> {
|
|
||||||
await this.getManualChatInput().fill(message);
|
|
||||||
await this.getManualChatModal().locator('.chat-input-send-button').click();
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Get all currently selected nodes on the canvas
|
* Get all currently selected nodes on the canvas
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import type { Locator } from '@playwright/test';
|
import type { Locator } from '@playwright/test';
|
||||||
|
|
||||||
import { BasePage } from './BasePage';
|
import { BasePage } from './BasePage';
|
||||||
|
import { LogsPanel } from './components/LogsPanel';
|
||||||
|
|
||||||
export class ExecutionsPage extends BasePage {
|
export class ExecutionsPage extends BasePage {
|
||||||
|
readonly logsPanel = new LogsPanel(this.getPreviewIframe().getByTestId('logs-panel'));
|
||||||
|
|
||||||
async clickDebugInEditorButton(): Promise<void> {
|
async clickDebugInEditorButton(): Promise<void> {
|
||||||
await this.clickButtonByName('Debug in editor');
|
await this.clickButtonByName('Debug in editor');
|
||||||
}
|
}
|
||||||
@@ -28,18 +31,6 @@ export class ExecutionsPage extends BasePage {
|
|||||||
return this.page.getByTestId('workflow-preview-iframe').contentFrame();
|
return this.page.getByTestId('workflow-preview-iframe').contentFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
getManualChatMessages(): Locator {
|
|
||||||
return this.getPreviewIframe().locator('.chat-messages-list .chat-message');
|
|
||||||
}
|
|
||||||
|
|
||||||
getLogsOverviewStatus() {
|
|
||||||
return this.getPreviewIframe().getByTestId('logs-overview-status');
|
|
||||||
}
|
|
||||||
|
|
||||||
getLogEntries(): Locator {
|
|
||||||
return this.getPreviewIframe().getByTestId('logs-overview-body').getByRole('treeitem');
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickLastExecutionItem(): Promise<void> {
|
async clickLastExecutionItem(): Promise<void> {
|
||||||
const executionItem = this.getLastExecutionItem();
|
const executionItem = this.getLastExecutionItem();
|
||||||
await executionItem.click();
|
await executionItem.click();
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
import type { Locator, Page } from '@playwright/test';
|
|
||||||
|
|
||||||
import { BasePage } from './BasePage';
|
|
||||||
|
|
||||||
export class LogsPage extends BasePage {
|
|
||||||
constructor(page: Page) {
|
|
||||||
super(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessors
|
|
||||||
*/
|
|
||||||
|
|
||||||
getOverviewStatus(): Locator {
|
|
||||||
return this.page.getByTestId('logs-overview-status');
|
|
||||||
}
|
|
||||||
|
|
||||||
getClearExecutionButton(): Locator {
|
|
||||||
return this.page
|
|
||||||
.getByTestId('logs-overview-header')
|
|
||||||
.locator('button')
|
|
||||||
.filter({ hasText: 'Clear execution' });
|
|
||||||
}
|
|
||||||
|
|
||||||
getLogEntries(): Locator {
|
|
||||||
return this.page.getByTestId('logs-overview-body').getByRole('treeitem');
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectedLogEntry(): Locator {
|
|
||||||
return this.page.getByTestId('logs-overview-body').getByRole('treeitem', { selected: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputPanel(): Locator {
|
|
||||||
return this.page.getByTestId('log-details-input');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputTableRows(): Locator {
|
|
||||||
return this.getInputPanel().locator('table tr');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputTbodyCell(row: number, col: number): Locator {
|
|
||||||
return this.getInputPanel().locator('table tbody tr').nth(row).locator('td').nth(col);
|
|
||||||
}
|
|
||||||
|
|
||||||
getNodeErrorMessageHeader(): Locator {
|
|
||||||
return this.getOutputPanel().getByTestId('node-error-message');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputPanel(): Locator {
|
|
||||||
return this.page.getByTestId('log-details-output');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputTbodyCell(row: number, col: number): Locator {
|
|
||||||
return this.getOutputPanel().locator('table tbody tr').nth(row).locator('td').nth(col);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actions
|
|
||||||
*/
|
|
||||||
|
|
||||||
async openLogsPanel(): Promise<void> {
|
|
||||||
await this.page.getByTestId('logs-overview-header').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickLogEntryAtRow(rowIndex: number): Promise<void> {
|
|
||||||
await this.getLogEntries().nth(rowIndex).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleInputPanel(): Promise<void> {
|
|
||||||
await this.page.getByTestId('log-details-header').getByText('Input').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickOpenNdvAtRow(rowIndex: number): Promise<void> {
|
|
||||||
await this.getLogEntries().nth(rowIndex).hover();
|
|
||||||
await this.getLogEntries().nth(rowIndex).getByLabel('Open...').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickTriggerPartialExecutionAtRow(rowIndex: number): Promise<void> {
|
|
||||||
await this.getLogEntries().nth(rowIndex).hover();
|
|
||||||
await this.getLogEntries().nth(rowIndex).getByLabel('Execute step').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async setInputDisplayMode(mode: 'table' | 'ai' | 'json' | 'schema'): Promise<void> {
|
|
||||||
await this.getInputPanel().hover();
|
|
||||||
await this.getInputPanel().getByTestId(`radio-button-${mode}`).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async setOutputDisplayMode(mode: 'table' | 'ai' | 'json' | 'schema'): Promise<void> {
|
|
||||||
await this.getOutputPanel().hover();
|
|
||||||
await this.getOutputPanel().getByTestId(`radio-button-${mode}`).click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,15 @@ import type { Page } from '@playwright/test';
|
|||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
|
|
||||||
import { BasePage } from './BasePage';
|
import { BasePage } from './BasePage';
|
||||||
|
import { RunDataPanel } from './components/RunDataPanel';
|
||||||
import { NodeParameterHelper } from '../helpers/NodeParameterHelper';
|
import { NodeParameterHelper } from '../helpers/NodeParameterHelper';
|
||||||
import { EditFieldsNode } from './nodes/EditFieldsNode';
|
import { EditFieldsNode } from './nodes/EditFieldsNode';
|
||||||
|
|
||||||
export class NodeDetailsViewPage extends BasePage {
|
export class NodeDetailsViewPage extends BasePage {
|
||||||
readonly setupHelper: NodeParameterHelper;
|
readonly setupHelper: NodeParameterHelper;
|
||||||
readonly editFields: EditFieldsNode;
|
readonly editFields: EditFieldsNode;
|
||||||
|
readonly inputPanel = new RunDataPanel(this.page.getByTestId('ndv-input-panel'));
|
||||||
|
readonly outputPanel = new RunDataPanel(this.page.getByTestId('output-panel'));
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
super(page);
|
super(page);
|
||||||
@@ -49,18 +52,10 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
await this.clickByTestId('node-execute-button');
|
await this.clickByTestId('node-execute-button');
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputPanel() {
|
|
||||||
return this.page.getByTestId('output-panel');
|
|
||||||
}
|
|
||||||
|
|
||||||
getContainer() {
|
getContainer() {
|
||||||
return this.page.getByTestId('ndv');
|
return this.page.getByTestId('ndv');
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputPanel() {
|
|
||||||
return this.page.getByTestId('ndv-input-panel');
|
|
||||||
}
|
|
||||||
|
|
||||||
getParameterExpressionPreviewValue() {
|
getParameterExpressionPreviewValue() {
|
||||||
return this.page.getByTestId('parameter-expression-preview-value');
|
return this.page.getByTestId('parameter-expression-preview-value');
|
||||||
}
|
}
|
||||||
@@ -82,47 +77,15 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
return this.page.getByTestId('ndv-edit-pinned-data');
|
return this.page.getByTestId('ndv-edit-pinned-data');
|
||||||
}
|
}
|
||||||
|
|
||||||
getPinDataButton() {
|
|
||||||
return this.getOutputPanel().getByTestId('ndv-pin-data');
|
|
||||||
}
|
|
||||||
|
|
||||||
getRunDataPaneHeader() {
|
getRunDataPaneHeader() {
|
||||||
return this.page.getByTestId('run-data-pane-header');
|
return this.page.getByTestId('run-data-pane-header');
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputTable() {
|
|
||||||
return this.getOutputPanel().getByTestId('ndv-data-container').locator('table');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputDataContainer() {
|
|
||||||
return this.getOutputPanel().getByTestId('ndv-data-container');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputTableRows() {
|
|
||||||
return this.getOutputTable().locator('tr');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputTableHeaders() {
|
|
||||||
return this.getOutputTable().locator('thead th');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputTableRow(row: number) {
|
|
||||||
return this.getOutputTableRows().nth(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputTableCell(row: number, col: number) {
|
|
||||||
return this.getOutputTableRow(row).locator('td').nth(col);
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputTbodyCell(row: number, col: number) {
|
|
||||||
return this.getOutputTable().locator('tbody tr').nth(row).locator('td').nth(col);
|
|
||||||
}
|
|
||||||
|
|
||||||
async setPinnedData(data: object | string) {
|
async setPinnedData(data: object | string) {
|
||||||
const pinnedData = typeof data === 'string' ? data : JSON.stringify(data);
|
const pinnedData = typeof data === 'string' ? data : JSON.stringify(data);
|
||||||
await this.getEditPinnedDataButton().click();
|
await this.getEditPinnedDataButton().click();
|
||||||
|
|
||||||
const editor = this.getOutputPanel().locator('[contenteditable="true"]');
|
const editor = this.outputPanel.get().locator('[contenteditable="true"]');
|
||||||
await editor.waitFor();
|
await editor.waitFor();
|
||||||
await editor.click();
|
await editor.click();
|
||||||
await editor.fill(pinnedData);
|
await editor.fill(pinnedData);
|
||||||
@@ -133,7 +96,7 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
async pastePinnedData(data: object) {
|
async pastePinnedData(data: object) {
|
||||||
await this.getEditPinnedDataButton().click();
|
await this.getEditPinnedDataButton().click();
|
||||||
|
|
||||||
const editor = this.getOutputPanel().locator('[contenteditable="true"]');
|
const editor = this.outputPanel.get().locator('[contenteditable="true"]');
|
||||||
await editor.waitFor();
|
await editor.waitFor();
|
||||||
await editor.click();
|
await editor.click();
|
||||||
await editor.fill('');
|
await editor.fill('');
|
||||||
@@ -400,64 +363,16 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async switchInputMode(mode: 'Schema' | 'Table' | 'JSON' | 'Binary'): Promise<void> {
|
|
||||||
await this.getInputPanel().getByRole('radio', { name: mode }).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async switchOutputMode(mode: 'Schema' | 'Table' | 'JSON' | 'Binary'): Promise<void> {
|
|
||||||
await this.getOutputPanel().getByRole('radio', { name: mode }).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
getAssignmentCollectionContainer(paramName: string) {
|
getAssignmentCollectionContainer(paramName: string) {
|
||||||
return this.page.getByTestId(`assignment-collection-${paramName}`);
|
return this.page.getByTestId(`assignment-collection-${paramName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getJsonDataContainer() {
|
|
||||||
return this.getInputPanel().locator('.json-data');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputJsonProperty(propertyName: string) {
|
|
||||||
return this.getInputPanel()
|
|
||||||
.locator('.json-data')
|
|
||||||
.locator('span')
|
|
||||||
.filter({ hasText: new RegExp(`^"${propertyName}"$`) })
|
|
||||||
.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputJsonPropertyContaining(text: string) {
|
|
||||||
return this.getInputPanel()
|
|
||||||
.locator('.json-data')
|
|
||||||
.locator('span')
|
|
||||||
.filter({ hasText: `"${text}"` })
|
|
||||||
.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputSchemaItem(text: string) {
|
|
||||||
return this.getInputPanel()
|
|
||||||
.getByTestId('run-data-schema-item')
|
|
||||||
.locator('span')
|
|
||||||
.filter({ hasText: new RegExp(`^${text}$`) })
|
|
||||||
.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
getNodeInputOptions() {
|
|
||||||
return this.getInputPanel().getByTestId('ndv-input-select');
|
|
||||||
}
|
|
||||||
|
|
||||||
async selectInputNode(nodeName: string) {
|
async selectInputNode(nodeName: string) {
|
||||||
const inputSelect = this.getNodeInputOptions();
|
const inputSelect = this.inputPanel.getNodeInputOptions();
|
||||||
await inputSelect.click();
|
await inputSelect.click();
|
||||||
await this.page.getByRole('option', { name: nodeName }).click();
|
await this.page.getByRole('option', { name: nodeName }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputTableHeader(index: number = 0) {
|
|
||||||
return this.getInputPanel().locator('table th').nth(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputTbodyCell(row: number, col: number) {
|
|
||||||
return this.getInputPanel().locator('table tbody tr').nth(row).locator('td').nth(col);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAssignmentName(paramName: string, index = 0) {
|
getAssignmentName(paramName: string, index = 0) {
|
||||||
return this.getAssignmentCollectionContainer(paramName)
|
return this.getAssignmentCollectionContainer(paramName)
|
||||||
.getByTestId('assignment')
|
.getByTestId('assignment')
|
||||||
@@ -542,14 +457,6 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
await input.type(content);
|
await input.type(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputTable() {
|
|
||||||
return this.getInputPanel().locator('table');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputTableCellSpan(row: number, col: number, dataName: string) {
|
|
||||||
return this.getInputTbodyCell(row, col).locator(`span[data-name="${dataName}"]`).first();
|
|
||||||
}
|
|
||||||
|
|
||||||
getAddFieldToSortByButton() {
|
getAddFieldToSortByButton() {
|
||||||
return this.getNodeParameters().getByText('Add Field To Sort By');
|
return this.getNodeParameters().getByText('Add Field To Sort By');
|
||||||
}
|
}
|
||||||
@@ -562,7 +469,7 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getOutputPagination() {
|
getOutputPagination() {
|
||||||
return this.getOutputPanel().getByTestId('ndv-data-pagination');
|
return this.outputPanel.get().getByTestId('ndv-data-pagination');
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputPaginationPages() {
|
getOutputPaginationPages() {
|
||||||
@@ -580,10 +487,6 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
return parseInt(pageText ?? '1', 10);
|
return parseInt(pageText ?? '1', 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOutputPageContent(row: number = 0, col: number = 0): Promise<string> {
|
|
||||||
return (await this.getOutputTbodyCell(row, col).textContent()) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
async setParameterInputValue(parameterName: string, value: string): Promise<void> {
|
async setParameterInputValue(parameterName: string, value: string): Promise<void> {
|
||||||
const input = this.getParameterInput(parameterName).locator('input');
|
const input = this.getParameterInput(parameterName).locator('input');
|
||||||
await input.clear();
|
await input.clear();
|
||||||
@@ -598,32 +501,8 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
return this.page.getByTestId('node-error-description');
|
return this.page.getByTestId('node-error-description');
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputRunSelector() {
|
|
||||||
return this.getInputPanel().getByTestId('run-selector');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputRunSelector() {
|
|
||||||
return this.getOutputPanel().getByTestId('run-selector');
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleOutputRunLinking() {
|
|
||||||
await this.getOutputPanel().getByTestId('link-run').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleInputRunLinking() {
|
|
||||||
await this.getInputPanel().getByTestId('link-run').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputLinkRun() {
|
|
||||||
return this.getOutputPanel().getByTestId('link-run');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputLinkRun() {
|
|
||||||
return this.getInputPanel().getByTestId('link-run');
|
|
||||||
}
|
|
||||||
|
|
||||||
async isOutputRunLinkingEnabled() {
|
async isOutputRunLinkingEnabled() {
|
||||||
const linkButton = this.getOutputLinkRun();
|
const linkButton = this.outputPanel.getLinkRun();
|
||||||
const classList = await linkButton.getAttribute('class');
|
const classList = await linkButton.getAttribute('class');
|
||||||
return classList?.includes('linked') ?? false;
|
return classList?.includes('linked') ?? false;
|
||||||
}
|
}
|
||||||
@@ -631,51 +510,35 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
async ensureOutputRunLinking(shouldBeLinked: boolean = true) {
|
async ensureOutputRunLinking(shouldBeLinked: boolean = true) {
|
||||||
const isLinked = await this.isOutputRunLinkingEnabled();
|
const isLinked = await this.isOutputRunLinkingEnabled();
|
||||||
if (isLinked !== shouldBeLinked) {
|
if (isLinked !== shouldBeLinked) {
|
||||||
await this.toggleOutputRunLinking();
|
await this.outputPanel.getLinkRun().click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeInputRunSelector(value: string) {
|
async changeInputRunSelector(value: string) {
|
||||||
const selector = this.getInputRunSelector();
|
const selector = this.inputPanel.getRunSelector();
|
||||||
await selector.click();
|
await selector.click();
|
||||||
await this.page.getByRole('option', { name: value }).click();
|
await this.page.getByRole('option', { name: value }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeOutputRunSelector(value: string) {
|
async changeOutputRunSelector(value: string) {
|
||||||
const selector = this.getOutputRunSelector();
|
const selector = this.outputPanel.getRunSelector();
|
||||||
await selector.click();
|
await selector.click();
|
||||||
await this.page.getByRole('option', { name: value }).click();
|
await this.page.getByRole('option', { name: value }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getInputRunSelectorValue() {
|
async getInputRunSelectorValue() {
|
||||||
return await this.getInputRunSelector().locator('input').inputValue();
|
return await this.inputPanel.getRunSelectorInput().inputValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOutputRunSelectorValue() {
|
async getOutputRunSelectorValue() {
|
||||||
return await this.getOutputRunSelector().locator('input').inputValue();
|
return await this.outputPanel.getRunSelectorInput().inputValue();
|
||||||
}
|
|
||||||
|
|
||||||
getOutputDisplayMode() {
|
|
||||||
return this.getOutputPanel().getByTestId('ndv-output-display-mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
getSchemaViewItems() {
|
|
||||||
return this.getOutputPanel().locator('[data-test-id="run-data-schema-item"]');
|
|
||||||
}
|
|
||||||
|
|
||||||
getSchemaItem(key: string) {
|
|
||||||
return this.getSchemaViewItems().filter({ hasText: key });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async expandSchemaItem(itemText: string) {
|
async expandSchemaItem(itemText: string) {
|
||||||
const item = this.getSchemaItem(itemText);
|
const item = this.outputPanel.getSchemaItem(itemText);
|
||||||
await item.locator('.toggle').click();
|
await item.locator('.toggle').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
getPaginationContainer() {
|
|
||||||
return this.getOutputPanel().locator('[class*="_pagination"]');
|
|
||||||
}
|
|
||||||
|
|
||||||
getExecuteNodeButton() {
|
getExecuteNodeButton() {
|
||||||
return this.page.getByTestId('node-execute-button');
|
return this.page.getByTestId('node-execute-button');
|
||||||
}
|
}
|
||||||
@@ -724,34 +587,18 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
return this.page.getByTestId('node-version');
|
return this.page.getByTestId('node-version');
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputSearchInput() {
|
|
||||||
return this.getOutputPanel().getByTestId('ndv-search');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputSearchInput() {
|
|
||||||
return this.getInputPanel().getByTestId('ndv-search');
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchOutputData(searchTerm: string) {
|
async searchOutputData(searchTerm: string) {
|
||||||
const searchInput = this.getOutputSearchInput();
|
const searchInput = this.outputPanel.getSearchInput();
|
||||||
await searchInput.click();
|
await searchInput.click();
|
||||||
await searchInput.fill(searchTerm);
|
await searchInput.fill(searchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchInputData(searchTerm: string) {
|
async searchInputData(searchTerm: string) {
|
||||||
const searchInput = this.getInputSearchInput();
|
const searchInput = this.inputPanel.getSearchInput();
|
||||||
await searchInput.click();
|
await searchInput.click();
|
||||||
await searchInput.fill(searchTerm);
|
await searchInput.fill(searchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOutputItemsCount() {
|
|
||||||
return this.getOutputPanel().getByTestId('ndv-items-count');
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputItemsCount() {
|
|
||||||
return this.getInputPanel().getByTestId('ndv-items-count');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type multiple values into the first available text parameter field
|
* Type multiple values into the first available text parameter field
|
||||||
* Useful for testing multiple parameter changes
|
* Useful for testing multiple parameter changes
|
||||||
@@ -878,12 +725,4 @@ export class NodeDetailsViewPage extends BasePage {
|
|||||||
getInputSelect() {
|
getInputSelect() {
|
||||||
return this.page.getByTestId('ndv-input-select').locator('input');
|
return this.page.getByTestId('ndv-input-select').locator('input');
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputTableRows() {
|
|
||||||
return this.getInputTable().locator('tr');
|
|
||||||
}
|
|
||||||
|
|
||||||
getOutputRunSelectorInput() {
|
|
||||||
return this.getOutputPanel().locator('[data-test-id="run-selector"] input');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
92
packages/testing/playwright/pages/components/LogsPanel.ts
Normal file
92
packages/testing/playwright/pages/components/LogsPanel.ts
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import type { Locator } from '@playwright/test';
|
||||||
|
|
||||||
|
import { RunDataPanel } from './RunDataPanel';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for the log view with configurable root element.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // Include in a page
|
||||||
|
* class ExamplePage {
|
||||||
|
* readonly logsPanel = new LogsPanel(this.page.getByTestId('logs-panel'));
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Usage in a test
|
||||||
|
* await expect(n8n.example.logsPage.getLogEntries()).toHaveCount(2);
|
||||||
|
*/
|
||||||
|
export class LogsPanel {
|
||||||
|
readonly inputPanel = new RunDataPanel(this.root.getByTestId('log-details-input'));
|
||||||
|
readonly outputPanel = new RunDataPanel(this.root.getByTestId('log-details-output'));
|
||||||
|
|
||||||
|
constructor(private root: Locator) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessors
|
||||||
|
*/
|
||||||
|
|
||||||
|
getOverviewStatus(): Locator {
|
||||||
|
return this.root.getByTestId('logs-overview-status');
|
||||||
|
}
|
||||||
|
|
||||||
|
getClearExecutionButton(): Locator {
|
||||||
|
return this.root
|
||||||
|
.getByTestId('logs-overview-header')
|
||||||
|
.locator('button')
|
||||||
|
.filter({ hasText: 'Clear execution' });
|
||||||
|
}
|
||||||
|
|
||||||
|
getLogEntries(): Locator {
|
||||||
|
return this.root.getByTestId('logs-overview-body').getByRole('treeitem');
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectedLogEntry(): Locator {
|
||||||
|
return this.root.getByTestId('logs-overview-body').getByRole('treeitem', { selected: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
getManualChatModal(): Locator {
|
||||||
|
return this.root.getByTestId('canvas-chat');
|
||||||
|
}
|
||||||
|
|
||||||
|
getManualChatInput(): Locator {
|
||||||
|
return this.getManualChatModal().locator('.chat-inputs textarea');
|
||||||
|
}
|
||||||
|
|
||||||
|
getManualChatMessages(): Locator {
|
||||||
|
return this.getManualChatModal().locator('.chat-messages-list .chat-message');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions
|
||||||
|
*/
|
||||||
|
|
||||||
|
async open(): Promise<void> {
|
||||||
|
await this.root.getByTestId('logs-overview-header').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickLogEntryAtRow(rowIndex: number): Promise<void> {
|
||||||
|
await this.getLogEntries().nth(rowIndex).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleInputPanel(): Promise<void> {
|
||||||
|
await this.root.getByTestId('log-details-header').getByText('Input').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickOpenNdvAtRow(rowIndex: number): Promise<void> {
|
||||||
|
await this.getLogEntries().nth(rowIndex).hover();
|
||||||
|
await this.getLogEntries().nth(rowIndex).getByLabel('Open...').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickTriggerPartialExecutionAtRow(rowIndex: number): Promise<void> {
|
||||||
|
await this.getLogEntries().nth(rowIndex).hover();
|
||||||
|
await this.getLogEntries().nth(rowIndex).getByLabel('Execute step').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearExecutionData(): Promise<void> {
|
||||||
|
await this.root.getByTestId('clear-execution-data-button').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendManualChatMessage(message: string): Promise<void> {
|
||||||
|
await this.getManualChatInput().fill(message);
|
||||||
|
await this.getManualChatModal().locator('.chat-input-send-button').click();
|
||||||
|
}
|
||||||
|
}
|
||||||
125
packages/testing/playwright/pages/components/RunDataPanel.ts
Normal file
125
packages/testing/playwright/pages/components/RunDataPanel.ts
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import type { Locator } from '@playwright/test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object for the run data view with configurable root element.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // Include in a page
|
||||||
|
* class ExamplePage {
|
||||||
|
* readonly runDataPanel = new RunDataPanel(this.page.getByTestId('run-data'));
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Usage in a test
|
||||||
|
* await n8n.example.runDataPanel.getRunSelector().click();
|
||||||
|
*/
|
||||||
|
export class RunDataPanel {
|
||||||
|
constructor(private root: Locator) {}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return this.root;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunSelector() {
|
||||||
|
return this.root.getByTestId('run-selector');
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunSelectorInput() {
|
||||||
|
return this.root.locator('[data-test-id="run-selector"] input');
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemsCount() {
|
||||||
|
return this.root.getByTestId('ndv-items-count');
|
||||||
|
}
|
||||||
|
|
||||||
|
getSearchInput() {
|
||||||
|
return this.root.getByTestId('ndv-search');
|
||||||
|
}
|
||||||
|
|
||||||
|
getDataContainer() {
|
||||||
|
return this.root.getByTestId('ndv-data-container');
|
||||||
|
}
|
||||||
|
|
||||||
|
getPinDataButton() {
|
||||||
|
return this.root.getByTestId('ndv-pin-data');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTable() {
|
||||||
|
return this.root.locator('table');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableHeaders() {
|
||||||
|
return this.root.locator('table th');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableHeader(index: number) {
|
||||||
|
return this.root.locator('table th').nth(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableRows() {
|
||||||
|
return this.root.locator('tr');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableRow(index: number) {
|
||||||
|
return this.root.locator('tr').nth(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTbodyCell(row: number, col: number) {
|
||||||
|
return this.root.locator('table tbody tr').nth(row).locator('td').nth(col);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableCellSpan(row: number, col: number, dataName: string) {
|
||||||
|
return this.getTbodyCell(row, col).locator(`span[data-name="${dataName}"]`).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
getJsonDataContainer() {
|
||||||
|
return this.root.locator('.json-data');
|
||||||
|
}
|
||||||
|
|
||||||
|
getJsonProperty(propertyName: string) {
|
||||||
|
return this.root
|
||||||
|
.locator('.json-data')
|
||||||
|
.locator('span')
|
||||||
|
.filter({ hasText: new RegExp(`^"${propertyName}"$`) })
|
||||||
|
.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
getJsonPropertyContaining(text: string) {
|
||||||
|
return this.root
|
||||||
|
.locator('.json-data')
|
||||||
|
.locator('span')
|
||||||
|
.filter({ hasText: `"${text}"` })
|
||||||
|
.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSchemaItems() {
|
||||||
|
return this.root.getByTestId('run-data-schema-item');
|
||||||
|
}
|
||||||
|
|
||||||
|
getSchemaItem(text: string) {
|
||||||
|
return this.getSchemaItems().filter({ hasText: text }).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSchemaItemText(text: string) {
|
||||||
|
return this.getSchemaItems().locator('span').filter({ hasText: text }).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeInputOptions() {
|
||||||
|
return this.root.getByTestId('ndv-input-select');
|
||||||
|
}
|
||||||
|
|
||||||
|
getLinkRun() {
|
||||||
|
return this.root.getByTestId('link-run');
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeErrorMessageHeader(): Locator {
|
||||||
|
return this.root.getByTestId('node-error-message');
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleInputRunLinking() {
|
||||||
|
await this.root.getByTestId('link-run').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async switchDisplayMode(mode: 'table' | 'ai' | 'json' | 'schema' | 'binary'): Promise<void> {
|
||||||
|
await this.root.getByTestId(`radio-button-${mode}`).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ 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';
|
||||||
import { LogsPage } from './LogsPage';
|
|
||||||
import { NodeDetailsViewPage } from './NodeDetailsViewPage';
|
import { NodeDetailsViewPage } from './NodeDetailsViewPage';
|
||||||
import { NotificationsPage } from './NotificationsPage';
|
import { NotificationsPage } from './NotificationsPage';
|
||||||
import { NpsSurveyPage } from './NpsSurveyPage';
|
import { NpsSurveyPage } from './NpsSurveyPage';
|
||||||
@@ -39,7 +38,6 @@ export class n8nPage {
|
|||||||
readonly demo: DemoPage;
|
readonly demo: DemoPage;
|
||||||
readonly iframe: IframePage;
|
readonly iframe: IframePage;
|
||||||
readonly interactions: InteractionsPage;
|
readonly interactions: InteractionsPage;
|
||||||
readonly logs: LogsPage;
|
|
||||||
readonly ndv: NodeDetailsViewPage;
|
readonly ndv: NodeDetailsViewPage;
|
||||||
readonly npsSurvey: NpsSurveyPage;
|
readonly npsSurvey: NpsSurveyPage;
|
||||||
readonly projectSettings: ProjectSettingsPage;
|
readonly projectSettings: ProjectSettingsPage;
|
||||||
@@ -74,7 +72,6 @@ export class n8nPage {
|
|||||||
this.demo = new DemoPage(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.logs = new LogsPage(page);
|
|
||||||
this.ndv = new NodeDetailsViewPage(page);
|
this.ndv = new NodeDetailsViewPage(page);
|
||||||
this.npsSurvey = new NpsSurveyPage(page);
|
this.npsSurvey = new NpsSurveyPage(page);
|
||||||
this.projectSettings = new ProjectSettingsPage(page);
|
this.projectSettings = new ProjectSettingsPage(page);
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ test.describe('Data pinning', () => {
|
|||||||
await n8n.canvas.addNode(NODES.SCHEDULE_TRIGGER);
|
await n8n.canvas.addNode(NODES.SCHEDULE_TRIGGER);
|
||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
|
|
||||||
const prevValue = await n8n.ndv.getOutputTbodyCell(0, 0).textContent();
|
const prevValue = await n8n.ndv.outputPanel.getTbodyCell(0, 0).textContent();
|
||||||
|
|
||||||
await n8n.ndv.togglePinData();
|
await n8n.ndv.togglePinData();
|
||||||
await n8n.ndv.close();
|
await n8n.ndv.close();
|
||||||
@@ -48,7 +48,7 @@ test.describe('Data pinning', () => {
|
|||||||
await n8n.canvas.clickExecuteWorkflowButton();
|
await n8n.canvas.clickExecuteWorkflowButton();
|
||||||
await n8n.canvas.openNode(NODES.SCHEDULE_TRIGGER);
|
await n8n.canvas.openNode(NODES.SCHEDULE_TRIGGER);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toHaveText(prevValue ?? '');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toHaveText(prevValue ?? '');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should be able to set custom pinned data', async ({ n8n }) => {
|
test('should be able to set custom pinned data', async ({ n8n }) => {
|
||||||
@@ -56,21 +56,21 @@ test.describe('Data pinning', () => {
|
|||||||
await n8n.canvas.addNode(NODES.SCHEDULE_TRIGGER);
|
await n8n.canvas.addNode(NODES.SCHEDULE_TRIGGER);
|
||||||
|
|
||||||
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
||||||
await expect(n8n.ndv.getPinDataButton()).toBeHidden();
|
await expect(n8n.ndv.outputPanel.getPinDataButton()).toBeHidden();
|
||||||
|
|
||||||
await n8n.ndv.setPinnedData([{ test: 1 }]);
|
await n8n.ndv.setPinnedData([{ test: 1 }]);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableRows()).toHaveCount(2);
|
await expect(n8n.ndv.outputPanel.getTableRows()).toHaveCount(2);
|
||||||
await expect(n8n.ndv.getOutputTableHeaders()).toHaveCount(2);
|
await expect(n8n.ndv.outputPanel.getTableHeaders()).toHaveCount(2);
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('test');
|
await expect(n8n.ndv.outputPanel.getTableHeaders().first()).toContainText('test');
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toContainText('1');
|
||||||
|
|
||||||
await n8n.ndv.close();
|
await n8n.ndv.close();
|
||||||
await n8n.canvas.clickSaveWorkflowButton();
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
await n8n.canvas.openNode(NODES.SCHEDULE_TRIGGER);
|
await n8n.canvas.openNode(NODES.SCHEDULE_TRIGGER);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('test');
|
await expect(n8n.ndv.outputPanel.getTableHeaders().first()).toContainText('test');
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toContainText('1');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should display pin data edit button for Webhook node', async ({ n8n }) => {
|
test('should display pin data edit button for Webhook node', async ({ n8n }) => {
|
||||||
@@ -92,7 +92,7 @@ test.describe('Data pinning', () => {
|
|||||||
await expect(n8n.ndv.getContainer()).toBeVisible();
|
await expect(n8n.ndv.getContainer()).toBeVisible();
|
||||||
|
|
||||||
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
||||||
await expect(n8n.ndv.getPinDataButton()).toBeHidden();
|
await expect(n8n.ndv.outputPanel.getPinDataButton()).toBeHidden();
|
||||||
|
|
||||||
await n8n.ndv.setPinnedData([{ test: 1 }]);
|
await n8n.ndv.setPinnedData([{ test: 1 }]);
|
||||||
await n8n.ndv.close();
|
await n8n.ndv.close();
|
||||||
@@ -101,8 +101,8 @@ test.describe('Data pinning', () => {
|
|||||||
await n8n.canvas.clickSaveWorkflowButton();
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
await n8n.canvas.openNode('Edit Fields1');
|
await n8n.canvas.openNode('Edit Fields1');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('test');
|
await expect(n8n.ndv.outputPanel.getTableHeader(0)).toContainText('test');
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toContainText('1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ test.describe('Data pinning', () => {
|
|||||||
|
|
||||||
await expect(n8n.ndv.getContainer()).toBeVisible();
|
await expect(n8n.ndv.getContainer()).toBeVisible();
|
||||||
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
||||||
await expect(n8n.ndv.getPinDataButton()).toBeHidden();
|
await expect(n8n.ndv.outputPanel.getPinDataButton()).toBeHidden();
|
||||||
|
|
||||||
const largeData = [{ test: '1'.repeat(maxPinnedDataSize + 1000) }];
|
const largeData = [{ test: '1'.repeat(maxPinnedDataSize + 1000) }];
|
||||||
await n8n.ndv.setPinnedData(largeData);
|
await n8n.ndv.setPinnedData(largeData);
|
||||||
@@ -146,7 +146,7 @@ test.describe('Data pinning', () => {
|
|||||||
|
|
||||||
await expect(n8n.ndv.getContainer()).toBeVisible();
|
await expect(n8n.ndv.getContainer()).toBeVisible();
|
||||||
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
await expect(n8n.ndv.getEditPinnedDataButton()).toBeVisible();
|
||||||
await expect(n8n.ndv.getPinDataButton()).toBeHidden();
|
await expect(n8n.ndv.outputPanel.getPinDataButton()).toBeHidden();
|
||||||
|
|
||||||
await n8n.ndv.setPinnedData('[ { "name": "First item", "code": 2dsa }]');
|
await n8n.ndv.setPinnedData('[ { "name": "First item", "code": 2dsa }]');
|
||||||
|
|
||||||
@@ -202,8 +202,8 @@ test.describe('Data pinning', () => {
|
|||||||
|
|
||||||
await n8n.canvas.openNode(NODES.END);
|
await n8n.canvas.openNode(NODES.END);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableRow(1)).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableRow(1)).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableRow(1)).toContainText('pin-overwritten');
|
await expect(n8n.ndv.outputPanel.getTableRow(1)).toContainText('pin-overwritten');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should not use pin data in production webhook executions', async ({
|
test('should not use pin data in production webhook executions', async ({
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ test.describe('ADO-1338-ndv-missing-input-panel', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await n8n.canvas.openNode('Discourse1');
|
await n8n.canvas.openNode('Discourse1');
|
||||||
await expect(n8n.ndv.getInputPanel()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.get()).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ test.describe('Data Mapping', () => {
|
|||||||
|
|
||||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||||
await n8n.canvas.openNode('Set');
|
await n8n.canvas.openNode('Set');
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
|
|
||||||
await expect(n8n.ndv.getInputTable()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.getTable()).toBeVisible();
|
||||||
|
|
||||||
await expect(n8n.ndv.getParameterInputField('name')).toHaveValue('other');
|
await expect(n8n.ndv.getParameterInputField('name')).toHaveValue('other');
|
||||||
await expect(n8n.ndv.getParameterInputField('value')).toHaveValue('');
|
await expect(n8n.ndv.getParameterInputField('value')).toHaveValue('');
|
||||||
|
|
||||||
const countCell = n8n.ndv.getInputTableCellSpan(0, 0, 'count');
|
const countCell = n8n.ndv.inputPanel.getTableCellSpan(0, 0, 'count');
|
||||||
await expect(countCell).toBeVisible();
|
await expect(countCell).toBeVisible();
|
||||||
|
|
||||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||||
@@ -28,35 +28,35 @@ test.describe('Data Mapping', () => {
|
|||||||
);
|
);
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||||
|
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).hover();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).hover();
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||||
|
|
||||||
await n8n.ndv.getInputTbodyCell(1, 0).hover();
|
await n8n.ndv.inputPanel.getTbodyCell(1, 0).hover();
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('1');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('1');
|
||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTable()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTable()).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.getOutputTbodyCell(0, 0).hover();
|
await n8n.ndv.outputPanel.getTbodyCell(0, 0).hover();
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||||
|
|
||||||
await n8n.ndv.getOutputTbodyCell(1, 0).hover();
|
await n8n.ndv.outputPanel.getTbodyCell(1, 0).hover();
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('1');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('maps expressions from json view', async ({ n8n }) => {
|
test('maps expressions from json view', async ({ n8n }) => {
|
||||||
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
|
||||||
await n8n.canvas.openNode('Set');
|
await n8n.canvas.openNode('Set');
|
||||||
await n8n.ndv.switchInputMode('JSON');
|
await n8n.ndv.inputPanel.switchDisplayMode('json');
|
||||||
|
|
||||||
const expectedJsonText =
|
const expectedJsonText =
|
||||||
'[{"input": [{"count": 0,"with space": "!!","with.dot": "!!","with"quotes": "!!"}]},{"input": [{"count": 1}]}]';
|
'[{"input": [{"count": 0,"with space": "!!","with.dot": "!!","with"quotes": "!!"}]},{"input": [{"count": 1}]}]';
|
||||||
await expect(n8n.ndv.getInputPanel().getByText(expectedJsonText)).toBeVisible();
|
await expect(n8n.ndv.inputPanel.get().getByText(expectedJsonText)).toBeVisible();
|
||||||
|
|
||||||
await expect(n8n.ndv.getJsonDataContainer()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.getJsonDataContainer()).toBeVisible();
|
||||||
|
|
||||||
const inputSpan = n8n.ndv.getInputJsonProperty('input');
|
const inputSpan = n8n.ndv.inputPanel.getJsonProperty('input');
|
||||||
await expect(inputSpan).toBeVisible();
|
await expect(inputSpan).toBeVisible();
|
||||||
|
|
||||||
const valueParameterInput = n8n.ndv.getParameterInput('value');
|
const valueParameterInput = n8n.ndv.getParameterInput('value');
|
||||||
@@ -73,7 +73,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('Array:');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('Array:');
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('"count": 0');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('"count": 0');
|
||||||
|
|
||||||
const countSpan = n8n.ndv.getInputJsonPropertyContaining('count');
|
const countSpan = n8n.ndv.inputPanel.getJsonPropertyContaining('count');
|
||||||
await expect(countSpan).toBeVisible();
|
await expect(countSpan).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(
|
await n8n.interactions.precisionDragToTarget(
|
||||||
@@ -97,17 +97,21 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.canvas.openNode('Set1');
|
await n8n.canvas.openNode('Set1');
|
||||||
await n8n.ndv.executePrevious();
|
await n8n.ndv.executePrevious();
|
||||||
|
|
||||||
const scheduleNode = n8n.ndv.getInputPanel().getByText('Schedule Trigger');
|
const scheduleNode = n8n.ndv.inputPanel.get().getByText('Schedule Trigger');
|
||||||
await expect(scheduleNode).toBeVisible();
|
await expect(scheduleNode).toBeVisible();
|
||||||
await scheduleNode.click();
|
await scheduleNode.click();
|
||||||
|
|
||||||
const schemaItem = n8n.ndv.getInputSchemaItem('count');
|
const schemaItem = n8n.ndv.inputPanel.getSchemaItemText('count');
|
||||||
await expect(schemaItem).toBeVisible();
|
await expect(schemaItem).toBeVisible();
|
||||||
|
|
||||||
const valueParameterInput = n8n.ndv.getParameterInput('value');
|
const valueParameterInput = n8n.ndv.getParameterInput('value');
|
||||||
await expect(valueParameterInput).toBeVisible();
|
await expect(valueParameterInput).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(schemaItem, valueParameterInput, 'top');
|
await n8n.interactions.precisionDragToTarget(
|
||||||
|
schemaItem.locator('span'),
|
||||||
|
valueParameterInput,
|
||||||
|
'top',
|
||||||
|
);
|
||||||
|
|
||||||
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
await expect(n8n.ndv.getInlineExpressionEditorInput()).toHaveText(
|
||||||
"{{ $('Schedule Trigger').item.json.input[0].count }}",
|
"{{ $('Schedule Trigger').item.json.input[0].count }}",
|
||||||
@@ -115,10 +119,10 @@ test.describe('Data Mapping', () => {
|
|||||||
|
|
||||||
await n8n.page.keyboard.press('Escape');
|
await n8n.page.keyboard.press('Escape');
|
||||||
|
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
await n8n.ndv.selectInputNode('Schedule Trigger');
|
await n8n.ndv.selectInputNode('Schedule Trigger');
|
||||||
|
|
||||||
const headerElement = n8n.ndv.getInputTableHeader(0);
|
const headerElement = n8n.ndv.inputPanel.getTableHeader(0);
|
||||||
await expect(headerElement).toBeVisible();
|
await expect(headerElement).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(
|
await n8n.interactions.precisionDragToTarget(
|
||||||
@@ -137,9 +141,9 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.start.fromImportedWorkflow('Test_workflow-actions_paste-data.json');
|
await n8n.start.fromImportedWorkflow('Test_workflow-actions_paste-data.json');
|
||||||
await n8n.canvas.openNode('Set');
|
await n8n.canvas.openNode('Set');
|
||||||
await n8n.ndv.executePrevious();
|
await n8n.ndv.executePrevious();
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
|
|
||||||
await expect(n8n.ndv.getInputTable()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.getTable()).toBeVisible();
|
||||||
|
|
||||||
const addValueButton = n8n.ndv.getAddValueButton();
|
const addValueButton = n8n.ndv.getAddValueButton();
|
||||||
await expect(addValueButton).toBeVisible();
|
await expect(addValueButton).toBeVisible();
|
||||||
@@ -150,7 +154,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await expect(n8n.ndv.getParameterInputField('name')).toHaveValue('propertyName');
|
await expect(n8n.ndv.getParameterInputField('name')).toHaveValue('propertyName');
|
||||||
await expect(n8n.ndv.getParameterInputField('value')).toHaveValue('');
|
await expect(n8n.ndv.getParameterInputField('value')).toHaveValue('');
|
||||||
|
|
||||||
const firstHeader = n8n.ndv.getInputTableHeader(0);
|
const firstHeader = n8n.ndv.inputPanel.getTableHeader(0);
|
||||||
await expect(firstHeader).toBeVisible();
|
await expect(firstHeader).toBeVisible();
|
||||||
|
|
||||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||||
@@ -164,7 +168,7 @@ test.describe('Data Mapping', () => {
|
|||||||
const currentYear = new Date().getFullYear().toString();
|
const currentYear = new Date().getFullYear().toString();
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText(currentYear);
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText(currentYear);
|
||||||
|
|
||||||
const secondHeader = n8n.ndv.getInputTableHeader(1);
|
const secondHeader = n8n.ndv.inputPanel.getTableHeader(1);
|
||||||
await expect(secondHeader).toBeVisible();
|
await expect(secondHeader).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(
|
await n8n.interactions.precisionDragToTarget(
|
||||||
@@ -185,7 +189,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.ndv.getParameterInputField('value').clear();
|
await n8n.ndv.getParameterInputField('value').clear();
|
||||||
await n8n.page.keyboard.press('Escape');
|
await n8n.page.keyboard.press('Escape');
|
||||||
|
|
||||||
const countSchemaItem = n8n.ndv.getInputSchemaItem('count');
|
const countSchemaItem = n8n.ndv.inputPanel.getSchemaItemText('count');
|
||||||
await expect(countSchemaItem).toBeVisible();
|
await expect(countSchemaItem).toBeVisible();
|
||||||
|
|
||||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||||
@@ -195,7 +199,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.page.keyboard.press('Escape');
|
await n8n.page.keyboard.press('Escape');
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||||
|
|
||||||
const inputSchemaItem = n8n.ndv.getInputSchemaItem('input');
|
const inputSchemaItem = n8n.ndv.inputPanel.getSchemaItemText('input');
|
||||||
await expect(inputSchemaItem).toBeVisible();
|
await expect(inputSchemaItem).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'top');
|
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'top');
|
||||||
@@ -239,7 +243,7 @@ test.describe('Data Mapping', () => {
|
|||||||
const addFieldButton = n8n.ndv.getAddFieldToSortByButton();
|
const addFieldButton = n8n.ndv.getAddFieldToSortByButton();
|
||||||
await addFieldButton.click();
|
await addFieldButton.click();
|
||||||
|
|
||||||
const myCountSpan = n8n.ndv.getInputSchemaItem('my count');
|
const myCountSpan = n8n.ndv.inputPanel.getSchemaItemText('my count');
|
||||||
await expect(myCountSpan).toBeVisible();
|
await expect(myCountSpan).toBeVisible();
|
||||||
|
|
||||||
const fieldNameParameter = n8n.ndv.getParameterInput('fieldName');
|
const fieldNameParameter = n8n.ndv.getParameterInput('fieldName');
|
||||||
@@ -262,7 +266,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.ndv.fillParameterInputByName('value', 'fun');
|
await n8n.ndv.fillParameterInputByName('value', 'fun');
|
||||||
await n8n.ndv.getParameterInputField('value').clear();
|
await n8n.ndv.getParameterInputField('value').clear();
|
||||||
|
|
||||||
const countSchemaItem = n8n.ndv.getInputSchemaItem('count');
|
const countSchemaItem = n8n.ndv.inputPanel.getSchemaItemText('count');
|
||||||
await expect(countSchemaItem).toBeVisible();
|
await expect(countSchemaItem).toBeVisible();
|
||||||
|
|
||||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||||
@@ -272,7 +276,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.page.keyboard.press('Escape');
|
await n8n.page.keyboard.press('Escape');
|
||||||
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
await expect(n8n.ndv.getParameterExpressionPreviewValue()).toContainText('0');
|
||||||
|
|
||||||
const inputSchemaItem = n8n.ndv.getInputSchemaItem('input');
|
const inputSchemaItem = n8n.ndv.inputPanel.getSchemaItemText('input');
|
||||||
await expect(inputSchemaItem).toBeVisible();
|
await expect(inputSchemaItem).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'top');
|
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'top');
|
||||||
@@ -293,9 +297,9 @@ test.describe('Data Mapping', () => {
|
|||||||
|
|
||||||
await n8n.canvas.openNode('Set1');
|
await n8n.canvas.openNode('Set1');
|
||||||
await n8n.ndv.executePrevious();
|
await n8n.ndv.executePrevious();
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
|
|
||||||
const firstHeader = n8n.ndv.getInputTableHeader(0);
|
const firstHeader = n8n.ndv.inputPanel.getTableHeader(0);
|
||||||
await expect(firstHeader).toBeVisible();
|
await expect(firstHeader).toBeVisible();
|
||||||
|
|
||||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||||
@@ -314,7 +318,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await expect(n8n.ndv.getParameterSwitch('includeOtherFields')).toBeVisible();
|
await expect(n8n.ndv.getParameterSwitch('includeOtherFields')).toBeVisible();
|
||||||
await expect(n8n.ndv.getParameterTextInput('includeOtherFields')).toBeHidden();
|
await expect(n8n.ndv.getParameterTextInput('includeOtherFields')).toBeHidden();
|
||||||
|
|
||||||
const countSpan = n8n.ndv.getInputSchemaItem('count');
|
const countSpan = n8n.ndv.inputPanel.getSchemaItemText('count');
|
||||||
await expect(countSpan).toBeVisible();
|
await expect(countSpan).toBeVisible();
|
||||||
|
|
||||||
await countSpan.hover();
|
await countSpan.hover();
|
||||||
@@ -341,7 +345,7 @@ test.describe('Data Mapping', () => {
|
|||||||
await n8n.ndv.getInlineExpressionEditorContent().fill('hello world\n\nnewline');
|
await n8n.ndv.getInlineExpressionEditorContent().fill('hello world\n\nnewline');
|
||||||
await n8n.page.keyboard.press('Escape');
|
await n8n.page.keyboard.press('Escape');
|
||||||
|
|
||||||
const countSchemaItem = n8n.ndv.getInputSchemaItem('count');
|
const countSchemaItem = n8n.ndv.inputPanel.getSchemaItemText('count');
|
||||||
await expect(countSchemaItem).toBeVisible();
|
await expect(countSchemaItem).toBeVisible();
|
||||||
|
|
||||||
const valueParameter = n8n.ndv.getParameterInput('value');
|
const valueParameter = n8n.ndv.getParameterInput('value');
|
||||||
@@ -355,7 +359,7 @@ test.describe('Data Mapping', () => {
|
|||||||
'0hello world\n\nnewline',
|
'0hello world\n\nnewline',
|
||||||
);
|
);
|
||||||
|
|
||||||
const inputSchemaItem = n8n.ndv.getInputSchemaItem('input');
|
const inputSchemaItem = n8n.ndv.inputPanel.getSchemaItemText('input');
|
||||||
await expect(inputSchemaItem).toBeVisible();
|
await expect(inputSchemaItem).toBeVisible();
|
||||||
|
|
||||||
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'center');
|
await n8n.interactions.precisionDragToTarget(inputSchemaItem, valueParameter, 'center');
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ test.describe('Schedule Trigger node', () => {
|
|||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputPanel()).toContainText('timestamp');
|
await expect(n8n.ndv.outputPanel.get()).toContainText('timestamp');
|
||||||
|
|
||||||
await n8n.ndv.clickBackToCanvasButton();
|
await n8n.ndv.clickBackToCanvasButton();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,13 +15,12 @@ test.describe('ADO-2230 NDV Pagination Reset', () => {
|
|||||||
|
|
||||||
await expect(n8n.ndv.getOutputPaginationPages()).toHaveCount(5);
|
await expect(n8n.ndv.getOutputPaginationPages()).toHaveCount(5);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).not.toBeEmpty();
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).not.toBeEmpty();
|
||||||
const firstPageContent = await n8n.ndv.getOutputPageContent(0, 0);
|
const firstPageContent = await n8n.ndv.outputPanel.getTbodyCell(0, 0).textContent();
|
||||||
|
|
||||||
await n8n.ndv.navigateToOutputPage(4);
|
await n8n.ndv.navigateToOutputPage(4);
|
||||||
|
|
||||||
const fourthPageContent = await n8n.ndv.getOutputPageContent(0, 0);
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).not.toHaveText(firstPageContent ?? '');
|
||||||
expect(fourthPageContent).not.toBe(firstPageContent);
|
|
||||||
|
|
||||||
await n8n.ndv.setParameterInputValue('randomDataCount', '20');
|
await n8n.ndv.setParameterInputValue('randomDataCount', '20');
|
||||||
|
|
||||||
@@ -30,6 +29,6 @@ test.describe('ADO-2230 NDV Pagination Reset', () => {
|
|||||||
|
|
||||||
await expect(n8n.ndv.getOutputPaginationPages()).toHaveCount(2);
|
await expect(n8n.ndv.getOutputPaginationPages()).toHaveCount(2);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).not.toBeEmpty();
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).not.toBeEmpty();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,19 +39,19 @@ test.describe('Resource Mapper', () => {
|
|||||||
await n8n.ndv.fillParameterInputByName('age', '30');
|
await n8n.ndv.fillParameterInputByName('age', '30');
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'name' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'name' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'age' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'age' })).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.getResourceMapperRemoveFieldButton('name').click();
|
await n8n.ndv.getResourceMapperRemoveFieldButton('name').click();
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getParameterInput('id')).toBeVisible();
|
await expect(n8n.ndv.getParameterInput('id')).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getParameterInput('age')).toBeVisible();
|
await expect(n8n.ndv.getParameterInput('age')).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'age' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'age' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getParameterInput('name')).toHaveCount(0);
|
await expect(n8n.ndv.getParameterInput('name')).toHaveCount(0);
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'name' })).toHaveCount(0);
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'name' })).toHaveCount(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should correctly delete all fields', async ({ n8n }) => {
|
test('should correctly delete all fields', async ({ n8n }) => {
|
||||||
@@ -60,19 +60,19 @@ test.describe('Resource Mapper', () => {
|
|||||||
await n8n.ndv.fillParameterInputByName('age', '30');
|
await n8n.ndv.fillParameterInputByName('age', '30');
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'name' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'name' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'age' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'age' })).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.getResourceMapperColumnsOptionsButton().click();
|
await n8n.ndv.getResourceMapperColumnsOptionsButton().click();
|
||||||
await n8n.ndv.getResourceMapperRemoveAllFieldsOption().click();
|
await n8n.ndv.getResourceMapperRemoveAllFieldsOption().click();
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getParameterInput('id')).toBeVisible();
|
await expect(n8n.ndv.getParameterInput('id')).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'id' })).toBeVisible();
|
||||||
await expect(n8n.ndv.getParameterInput('name')).toHaveCount(0);
|
await expect(n8n.ndv.getParameterInput('name')).toHaveCount(0);
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'name' })).toHaveCount(0);
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'name' })).toHaveCount(0);
|
||||||
await expect(n8n.ndv.getParameterInput('age')).toHaveCount(0);
|
await expect(n8n.ndv.getParameterInput('age')).toHaveCount(0);
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().filter({ hasText: 'age' })).toHaveCount(0);
|
await expect(n8n.ndv.outputPanel.getTableHeaders().filter({ hasText: 'age' })).toHaveCount(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ test.describe('Demo', () => {
|
|||||||
await n8n.demo.importWorkflow(workflowWithPinned);
|
await n8n.demo.importWorkflow(workflowWithPinned);
|
||||||
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(2);
|
||||||
await n8n.canvas.openNode('Webhook');
|
await n8n.canvas.openNode('Webhook');
|
||||||
await expect(n8n.ndv.getOutputTableHeaders().first()).toContainText('headers');
|
await expect(n8n.ndv.outputPanel.getTableHeaders().first()).toContainText('headers');
|
||||||
await expect(n8n.ndv.getOutputTableCell(1, 3)).toContainText('dragons');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 3)).toContainText('dragons');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can override theme to dark', async ({ n8n }) => {
|
test('can override theme to dark', async ({ n8n }) => {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ test.describe('NDV', () => {
|
|||||||
const canvasNodes = n8n.canvas.getCanvasNodes();
|
const canvasNodes = n8n.canvas.getCanvasNodes();
|
||||||
await canvasNodes.last().dblclick();
|
await canvasNodes.last().dblclick();
|
||||||
await expect(n8n.ndv.getContainer()).toBeVisible();
|
await expect(n8n.ndv.getContainer()).toBeVisible();
|
||||||
await expect(n8n.ndv.getInputPanel()).toContainText('Wire me up');
|
await expect(n8n.ndv.inputPanel.get()).toContainText('Wire me up');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should test webhook node', async ({ n8n }) => {
|
test('should test webhook node', async ({ n8n }) => {
|
||||||
@@ -42,8 +42,8 @@ test.describe('NDV', () => {
|
|||||||
const response = await n8n.ndv.makeWebhookRequest(webhookUrl as string);
|
const response = await n8n.ndv.makeWebhookRequest(webhookUrl as string);
|
||||||
expect(response.status()).toBe(200);
|
expect(response.status()).toBe(200);
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputDataContainer()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getDataContainer()).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should change input and go back to canvas', async ({ n8n }) => {
|
test('should change input and go back to canvas', async ({ n8n }) => {
|
||||||
@@ -52,11 +52,11 @@ test.describe('NDV', () => {
|
|||||||
await n8n.canvas.getCanvasNodes().last().dblclick();
|
await n8n.canvas.getCanvasNodes().last().dblclick();
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
|
|
||||||
await n8n.ndv.getNodeInputOptions().last().click();
|
await n8n.ndv.inputPanel.getNodeInputOptions().last().click();
|
||||||
|
|
||||||
await expect(n8n.ndv.getInputPanel()).toContainText('start');
|
await expect(n8n.ndv.inputPanel.get()).toContainText('start');
|
||||||
|
|
||||||
await n8n.ndv.clickBackToCanvasButton();
|
await n8n.ndv.clickBackToCanvasButton();
|
||||||
await expect(n8n.ndv.getContainer()).toBeHidden();
|
await expect(n8n.ndv.getContainer()).toBeHidden();
|
||||||
@@ -175,20 +175,20 @@ test.describe('NDV', () => {
|
|||||||
|
|
||||||
test('should switch to output schema view and validate it', async ({ n8n }) => {
|
test('should switch to output schema view and validate it', async ({ n8n }) => {
|
||||||
await setupSchemaWorkflow(n8n);
|
await setupSchemaWorkflow(n8n);
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
|
|
||||||
for (const key of schemaKeys) {
|
for (const key of schemaKeys) {
|
||||||
await expect(n8n.ndv.getSchemaViewItems().filter({ hasText: key })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getSchemaItem(key)).toBeVisible();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should preserve schema view after execution', async ({ n8n }) => {
|
test('should preserve schema view after execution', async ({ n8n }) => {
|
||||||
await setupSchemaWorkflow(n8n);
|
await setupSchemaWorkflow(n8n);
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
for (const key of schemaKeys) {
|
for (const key of schemaKeys) {
|
||||||
await expect(n8n.ndv.getSchemaViewItems().filter({ hasText: key })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getSchemaItem(key)).toBeVisible();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -196,17 +196,17 @@ test.describe('NDV', () => {
|
|||||||
await setupSchemaWorkflow(n8n);
|
await setupSchemaWorkflow(n8n);
|
||||||
const expandedObjectProps = ['prop1', 'prop2'];
|
const expandedObjectProps = ['prop1', 'prop2'];
|
||||||
|
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
|
|
||||||
for (const key of expandedObjectProps) {
|
for (const key of expandedObjectProps) {
|
||||||
await expect(n8n.ndv.getSchemaViewItems().filter({ hasText: key })).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getSchemaItem(key)).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
const objectValueItem = n8n.ndv.getSchemaViewItems().filter({ hasText: 'objectValue' });
|
const objectValueItem = n8n.ndv.outputPanel.getSchemaItem('objectValue');
|
||||||
await objectValueItem.locator('.toggle').click();
|
await objectValueItem.locator('.toggle').click();
|
||||||
|
|
||||||
for (const key of expandedObjectProps) {
|
for (const key of expandedObjectProps) {
|
||||||
await expect(n8n.ndv.getSchemaViewItems().filter({ hasText: key })).not.toBeInViewport();
|
await expect(n8n.ndv.outputPanel.getSchemaItem(key)).not.toBeInViewport();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -222,14 +222,14 @@ test.describe('NDV', () => {
|
|||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputPanel().getByText('5 items')).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get().getByText('5 items')).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
|
|
||||||
const schemaItemsCount = await n8n.ndv.getSchemaViewItems().count();
|
const schemaItemsCount = await n8n.ndv.outputPanel.getSchemaItems().count();
|
||||||
expect(schemaItemsCount).toBeGreaterThan(0);
|
expect(schemaItemsCount).toBeGreaterThan(0);
|
||||||
|
|
||||||
await n8n.ndv.switchOutputMode('JSON');
|
await n8n.ndv.outputPanel.switchDisplayMode('json');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should display large schema', async ({ n8n }) => {
|
test('should display large schema', async ({ n8n }) => {
|
||||||
@@ -237,12 +237,12 @@ test.describe('NDV', () => {
|
|||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.canvas.openNode('Set');
|
await n8n.canvas.openNode('Set');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputPanel().getByText('20 items')).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get().getByText('20 items')).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputPanel().locator('[class*="_pagination"]')).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get().locator('[class*="_pagination"]')).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputPanel().locator('[class*="_pagination"]')).toBeHidden();
|
await expect(n8n.ndv.outputPanel.get().locator('[class*="_pagination"]')).toBeHidden();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -356,16 +356,16 @@ test.describe('NDV', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await n8n.canvas.openNode('Edit Fields');
|
await n8n.canvas.openNode('Edit Fields');
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.searchOutputData('US');
|
await n8n.ndv.searchOutputData('US');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableRow(1).locator('mark')).toContainText('US');
|
await expect(n8n.ndv.outputPanel.getTableRow(1).locator('mark')).toContainText('US');
|
||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputSearchInput()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getSearchInput()).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputSearchInput()).toHaveValue('US');
|
await expect(n8n.ndv.outputPanel.getSearchInput()).toHaveValue('US');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Should render xml and html tags as strings and can search', async ({ n8n }) => {
|
test('Should render xml and html tags as strings and can search', async ({ n8n }) => {
|
||||||
@@ -375,23 +375,23 @@ test.describe('NDV', () => {
|
|||||||
);
|
);
|
||||||
await n8n.canvas.openNode('Edit Fields');
|
await n8n.canvas.openNode('Edit Fields');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputPanel().locator('[class*="active"]')).toContainText('Table');
|
await expect(n8n.ndv.outputPanel.get().locator('[class*="active"]')).toContainText('Table');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableRow(1)).toContainText(
|
await expect(n8n.ndv.outputPanel.getTableRow(1)).toContainText(
|
||||||
'<?xml version="1.0" encoding="UTF-8"?> <library>',
|
'<?xml version="1.0" encoding="UTF-8"?> <library>',
|
||||||
);
|
);
|
||||||
|
|
||||||
await n8n.page.keyboard.press('/');
|
await n8n.page.keyboard.press('/');
|
||||||
|
|
||||||
const searchInput = n8n.ndv.getOutputSearchInput();
|
const searchInput = n8n.ndv.outputPanel.getSearchInput();
|
||||||
await expect(searchInput).toBeFocused();
|
await expect(searchInput).toBeFocused();
|
||||||
await searchInput.fill('<lib');
|
await searchInput.fill('<lib');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputTableRow(1).locator('mark')).toContainText('<lib');
|
await expect(n8n.ndv.outputPanel.getTableRow(1).locator('mark')).toContainText('<lib');
|
||||||
|
|
||||||
await n8n.ndv.switchOutputMode('JSON');
|
await n8n.ndv.outputPanel.switchDisplayMode('json');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputDataContainer().locator('.json-data')).toBeVisible();
|
await expect(n8n.ndv.outputPanel.getDataContainer().locator('.json-data')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Run Data & Selectors - Advanced', () => {
|
test.describe('Run Data & Selectors - Advanced', () => {
|
||||||
@@ -403,39 +403,39 @@ test.describe('NDV', () => {
|
|||||||
);
|
);
|
||||||
await n8n.canvas.openNode('Set3');
|
await n8n.canvas.openNode('Set3');
|
||||||
|
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
await n8n.ndv.switchOutputMode('Table');
|
await n8n.ndv.outputPanel.switchDisplayMode('table');
|
||||||
|
|
||||||
await n8n.ndv.ensureOutputRunLinking(true);
|
await n8n.ndv.ensureOutputRunLinking(true);
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).click();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).click();
|
||||||
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
||||||
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
||||||
|
|
||||||
await n8n.ndv.changeOutputRunSelector('1 of 2 (6 items)');
|
await n8n.ndv.changeOutputRunSelector('1 of 2 (6 items)');
|
||||||
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('1 of 2 (6 items)');
|
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('1 of 2 (6 items)');
|
||||||
await expect(n8n.ndv.getInputTbodyCell(0, 0)).toHaveText('1111');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(0, 0)).toHaveText('1111');
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toHaveText('1111');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toHaveText('1111');
|
||||||
|
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).click();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).click();
|
||||||
await n8n.ndv.changeInputRunSelector('2 of 2 (6 items)');
|
await n8n.ndv.changeInputRunSelector('2 of 2 (6 items)');
|
||||||
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
||||||
|
|
||||||
await n8n.ndv.toggleOutputRunLinking();
|
await n8n.ndv.outputPanel.getLinkRun().click();
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).click();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).click();
|
||||||
await n8n.ndv.changeOutputRunSelector('1 of 2 (6 items)');
|
await n8n.ndv.changeOutputRunSelector('1 of 2 (6 items)');
|
||||||
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
||||||
|
|
||||||
await n8n.ndv.toggleOutputRunLinking();
|
await n8n.ndv.outputPanel.getLinkRun().click();
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).click();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).click();
|
||||||
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('1 of 2 (6 items)');
|
expect(await n8n.ndv.getInputRunSelectorValue()).toContain('1 of 2 (6 items)');
|
||||||
|
|
||||||
await n8n.ndv.toggleInputRunLinking();
|
await n8n.ndv.inputPanel.toggleInputRunLinking();
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).click();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).click();
|
||||||
await n8n.ndv.changeInputRunSelector('2 of 2 (6 items)');
|
await n8n.ndv.changeInputRunSelector('2 of 2 (6 items)');
|
||||||
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('1 of 2 (6 items)');
|
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('1 of 2 (6 items)');
|
||||||
|
|
||||||
await n8n.ndv.toggleInputRunLinking();
|
await n8n.ndv.inputPanel.toggleInputRunLinking();
|
||||||
await n8n.ndv.getInputTbodyCell(0, 0).click();
|
await n8n.ndv.inputPanel.getTbodyCell(0, 0).click();
|
||||||
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
expect(await n8n.ndv.getOutputRunSelectorValue()).toContain('2 of 2 (6 items)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -708,21 +708,21 @@ test.describe('NDV', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await n8n.canvas.openNode('Only Item 1');
|
await n8n.canvas.openNode('Only Item 1');
|
||||||
await expect(n8n.ndv.getInputPanel()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.get()).toBeVisible();
|
||||||
await n8n.ndv.switchInputMode('Schema');
|
await n8n.ndv.inputPanel.switchDisplayMode('schema');
|
||||||
await expect(n8n.ndv.getInputSchemaItem('onlyOnItem1')).toBeVisible();
|
await expect(n8n.ndv.inputPanel.getSchemaItem('onlyOnItem1')).toBeVisible();
|
||||||
await n8n.ndv.close();
|
await n8n.ndv.close();
|
||||||
|
|
||||||
await n8n.canvas.openNode('Only Item 2');
|
await n8n.canvas.openNode('Only Item 2');
|
||||||
await expect(n8n.ndv.getInputPanel()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.get()).toBeVisible();
|
||||||
await n8n.ndv.switchInputMode('Schema');
|
await n8n.ndv.inputPanel.switchDisplayMode('schema');
|
||||||
await expect(n8n.ndv.getInputSchemaItem('onlyOnItem2')).toBeVisible();
|
await expect(n8n.ndv.inputPanel.getSchemaItem('onlyOnItem2')).toBeVisible();
|
||||||
await n8n.ndv.close();
|
await n8n.ndv.close();
|
||||||
|
|
||||||
await n8n.canvas.openNode('Only Item 3');
|
await n8n.canvas.openNode('Only Item 3');
|
||||||
await expect(n8n.ndv.getInputPanel()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.get()).toBeVisible();
|
||||||
await n8n.ndv.switchInputMode('Schema');
|
await n8n.ndv.inputPanel.switchDisplayMode('schema');
|
||||||
await expect(n8n.ndv.getInputSchemaItem('onlyOnItem3')).toBeVisible();
|
await expect(n8n.ndv.inputPanel.getSchemaItem('onlyOnItem3')).toBeVisible();
|
||||||
await n8n.ndv.close();
|
await n8n.ndv.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -731,13 +731,13 @@ test.describe('NDV', () => {
|
|||||||
test('should not show items count when searching in schema view', async ({ n8n }) => {
|
test('should not show items count when searching in schema view', async ({ n8n }) => {
|
||||||
await n8n.canvas.importWorkflow('Test_ndv_search.json', 'NDV Search Test');
|
await n8n.canvas.importWorkflow('Test_ndv_search.json', 'NDV Search Test');
|
||||||
await n8n.canvas.openNode('Edit Fields');
|
await n8n.canvas.openNode('Edit Fields');
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
await n8n.ndv.searchOutputData('US');
|
await n8n.ndv.searchOutputData('US');
|
||||||
|
|
||||||
await expect(n8n.ndv.getOutputItemsCount()).toBeHidden();
|
await expect(n8n.ndv.outputPanel.getItemsCount()).toBeHidden();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should show additional tooltip when searching in schema view if no matches', async ({
|
test('should show additional tooltip when searching in schema view if no matches', async ({
|
||||||
@@ -746,14 +746,16 @@ test.describe('NDV', () => {
|
|||||||
await n8n.canvas.importWorkflow('Test_ndv_search.json', 'NDV Search Test');
|
await n8n.canvas.importWorkflow('Test_ndv_search.json', 'NDV Search Test');
|
||||||
|
|
||||||
await n8n.canvas.openNode('Edit Fields');
|
await n8n.canvas.openNode('Edit Fields');
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
await n8n.ndv.switchOutputMode('Schema');
|
await n8n.ndv.outputPanel.switchDisplayMode('schema');
|
||||||
await n8n.ndv.searchOutputData('foo');
|
await n8n.ndv.searchOutputData('foo');
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
n8n.ndv.getOutputPanel().getByText('To search field values, switch to table or JSON view.'),
|
n8n.ndv.outputPanel
|
||||||
|
.get()
|
||||||
|
.getByText('To search field values, switch to table or JSON view.'),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -768,14 +770,12 @@ test.describe('NDV', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await n8n.canvas.openNode('DebugHelper');
|
await n8n.canvas.openNode('DebugHelper');
|
||||||
await expect(n8n.ndv.getInputPanel()).toBeVisible();
|
await expect(n8n.ndv.inputPanel.get()).toBeVisible();
|
||||||
await expect(n8n.ndv.getOutputPanel()).toBeVisible();
|
await expect(n8n.ndv.outputPanel.get()).toBeVisible();
|
||||||
|
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(
|
await expect(n8n.ndv.inputPanel.getSchemaItem('a1')).toBeVisible();
|
||||||
n8n.ndv.getInputPanel().getByTestId('run-data-schema-item').filter({ hasText: 'a1' }),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,38 +25,42 @@ test.describe('Logs', () => {
|
|||||||
await setupRequirements({ workflow: 'Workflow_loop.json' });
|
await setupRequirements({ workflow: 'Workflow_loop.json' });
|
||||||
|
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(0);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(0);
|
||||||
|
|
||||||
await n8n.canvas.clickExecuteWorkflowButton();
|
await n8n.canvas.clickExecuteWorkflowButton();
|
||||||
await expect(n8n.logs.getOverviewStatus().filter({ hasText: 'Running' })).toBeVisible();
|
|
||||||
|
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(4);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(0)).toContainText(NODES.MANUAL_TRIGGER);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText(NODES.CODE);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(2)).toContainText(NODES.LOOP_OVER_ITEMS);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(3)).toContainText(NODES.WAIT);
|
|
||||||
|
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(6);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(4)).toContainText(NODES.LOOP_OVER_ITEMS);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(5)).toContainText(NODES.WAIT);
|
|
||||||
|
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(8);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(6)).toContainText(NODES.LOOP_OVER_ITEMS);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(7)).toContainText(NODES.WAIT);
|
|
||||||
|
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(10);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(8)).toContainText(NODES.LOOP_OVER_ITEMS);
|
|
||||||
await expect(n8n.logs.getLogEntries().nth(9)).toContainText(NODES.CODE1);
|
|
||||||
await expect(
|
await expect(
|
||||||
n8n.logs.getOverviewStatus().filter({ hasText: /Error in [\d.]+s/ }),
|
n8n.canvas.logsPanel.getOverviewStatus().filter({ hasText: 'Running' }),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
await expect(n8n.logs.getSelectedLogEntry()).toContainText(NODES.CODE1); // Errored node is automatically selected
|
|
||||||
await expect(n8n.logs.getNodeErrorMessageHeader()).toContainText('test!!! [line 1]');
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(4);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(0)).toContainText(NODES.MANUAL_TRIGGER);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText(NODES.CODE);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(2)).toContainText(NODES.LOOP_OVER_ITEMS);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(3)).toContainText(NODES.WAIT);
|
||||||
|
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(6);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(4)).toContainText(NODES.LOOP_OVER_ITEMS);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(5)).toContainText(NODES.WAIT);
|
||||||
|
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(8);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(6)).toContainText(NODES.LOOP_OVER_ITEMS);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(7)).toContainText(NODES.WAIT);
|
||||||
|
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(10);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(8)).toContainText(NODES.LOOP_OVER_ITEMS);
|
||||||
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(9)).toContainText(NODES.CODE1);
|
||||||
|
await expect(
|
||||||
|
n8n.canvas.logsPanel.getOverviewStatus().filter({ hasText: /Error in [\d.]+s/ }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(n8n.canvas.logsPanel.getSelectedLogEntry()).toContainText(NODES.CODE1); // Errored node is automatically selected
|
||||||
|
await expect(n8n.canvas.logsPanel.outputPanel.getNodeErrorMessageHeader()).toContainText(
|
||||||
|
'test!!! [line 1]',
|
||||||
|
);
|
||||||
await expect(n8n.canvas.getNodeIssuesByName(NODES.CODE1)).toBeVisible();
|
await expect(n8n.canvas.getNodeIssuesByName(NODES.CODE1)).toBeVisible();
|
||||||
|
|
||||||
await n8n.logs.getClearExecutionButton().click();
|
await n8n.canvas.logsPanel.getClearExecutionButton().click();
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(0);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(0);
|
||||||
await expect(n8n.canvas.getNodeIssuesByName(NODES.CODE1)).not.toBeVisible();
|
await expect(n8n.canvas.getNodeIssuesByName(NODES.CODE1)).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -64,22 +68,22 @@ test.describe('Logs', () => {
|
|||||||
await setupRequirements({ workflow: 'Workflow_if.json' });
|
await setupRequirements({ workflow: 'Workflow_if.json' });
|
||||||
|
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
|
|
||||||
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(6);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(6);
|
||||||
await expect(n8n.logs.getLogEntries().nth(0)).toContainText(NODES.SCHEDULE_TRIGGER);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(0)).toContainText(NODES.SCHEDULE_TRIGGER);
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText(NODES.CODE);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText(NODES.CODE);
|
||||||
await expect(n8n.logs.getLogEntries().nth(2)).toContainText(NODES.EDIT_FIELDS);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(2)).toContainText(NODES.EDIT_FIELDS);
|
||||||
await expect(n8n.logs.getLogEntries().nth(3)).toContainText(NODES.IF);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(3)).toContainText(NODES.IF);
|
||||||
await expect(n8n.logs.getLogEntries().nth(4)).toContainText(NODES.EDIT_FIELDS);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(4)).toContainText(NODES.EDIT_FIELDS);
|
||||||
await expect(n8n.logs.getLogEntries().nth(5)).toContainText(NODES.EDIT_FIELDS);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(5)).toContainText(NODES.EDIT_FIELDS);
|
||||||
|
|
||||||
await n8n.logs.clickTriggerPartialExecutionAtRow(3);
|
await n8n.canvas.logsPanel.clickTriggerPartialExecutionAtRow(3);
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(3);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(3);
|
||||||
await expect(n8n.logs.getLogEntries().nth(0)).toContainText(NODES.SCHEDULE_TRIGGER);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(0)).toContainText(NODES.SCHEDULE_TRIGGER);
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText(NODES.CODE);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText(NODES.CODE);
|
||||||
await expect(n8n.logs.getLogEntries().nth(2)).toContainText(NODES.IF);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(2)).toContainText(NODES.IF);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: make it possible to test workflows with AI model end-to-end
|
// TODO: make it possible to test workflows with AI model end-to-end
|
||||||
@@ -90,37 +94,45 @@ test.describe('Logs', () => {
|
|||||||
await setupRequirements({ workflow: 'Workflow_ai_agent.json' });
|
await setupRequirements({ workflow: 'Workflow_ai_agent.json' });
|
||||||
|
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
await n8n.canvas.sendManualChatMessage('Hi!');
|
await n8n.canvas.logsPanel.sendManualChatMessage('Hi!');
|
||||||
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
||||||
await expect(n8n.canvas.getManualChatMessages().nth(0)).toContainText('Hi!');
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().nth(0)).toContainText('Hi!');
|
||||||
await expect(n8n.canvas.getManualChatMessages().nth(1)).toContainText(
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().nth(1)).toContainText(
|
||||||
'Hello from e2e model!!!',
|
'Hello from e2e model!!!',
|
||||||
);
|
);
|
||||||
await expect(n8n.logs.getLogEntries().nth(2)).toHaveText('E2E Chat Model');
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(2)).toHaveText('E2E Chat Model');
|
||||||
await n8n.logs.getLogEntries().nth(2).click();
|
await n8n.canvas.logsPanel.getLogEntries().nth(2).click();
|
||||||
|
|
||||||
await expect(n8n.logs.getOutputPanel()).toContainText('Hello from e2e model!!!');
|
await expect(n8n.canvas.logsPanel.outputPanel.get()).toContainText('Hello from e2e model!!!');
|
||||||
await n8n.logs.setOutputDisplayMode('table');
|
await n8n.canvas.logsPanel.outputPanel.switchDisplayMode('table');
|
||||||
await expect(n8n.logs.getOutputTbodyCell(0, 0)).toContainText(
|
await expect(n8n.canvas.logsPanel.outputPanel.getTbodyCell(0, 0)).toContainText(
|
||||||
'text:Hello from **e2e** model!!!',
|
'text:Hello from **e2e** model!!!',
|
||||||
);
|
);
|
||||||
await expect(n8n.logs.getOutputTbodyCell(0, 1)).toContainText('completionTokens:20');
|
await expect(n8n.canvas.logsPanel.outputPanel.getTbodyCell(0, 1)).toContainText(
|
||||||
await n8n.logs.setOutputDisplayMode('schema');
|
'completionTokens:20',
|
||||||
await expect(n8n.logs.getOutputPanel()).toContainText('generations[0]');
|
);
|
||||||
await expect(n8n.logs.getOutputPanel()).toContainText('Hello from **e2e** model!!!');
|
await n8n.canvas.logsPanel.outputPanel.switchDisplayMode('schema');
|
||||||
await n8n.logs.setOutputDisplayMode('json');
|
await expect(n8n.canvas.logsPanel.outputPanel.get()).toContainText('generations[0]');
|
||||||
await expect(n8n.logs.getOutputPanel()).toContainText('[{"response": {"generations": [');
|
await expect(n8n.canvas.logsPanel.outputPanel.get()).toContainText(
|
||||||
|
'Hello from **e2e** model!!!',
|
||||||
|
);
|
||||||
|
await n8n.canvas.logsPanel.outputPanel.switchDisplayMode('json');
|
||||||
|
await expect(n8n.canvas.logsPanel.outputPanel.get()).toContainText(
|
||||||
|
'[{"response": {"generations": [',
|
||||||
|
);
|
||||||
|
|
||||||
await n8n.logs.toggleInputPanel();
|
await n8n.canvas.logsPanel.toggleInputPanel();
|
||||||
await expect(n8n.logs.getInputPanel()).toContainText('Human: Hi!');
|
await expect(n8n.canvas.logsPanel.inputPanel.get()).toContainText('Human: Hi!');
|
||||||
await n8n.logs.setInputDisplayMode('table');
|
await n8n.canvas.logsPanel.inputPanel.switchDisplayMode('table');
|
||||||
await expect(n8n.logs.getInputTbodyCell(0, 0)).toContainText('0:Human: Hi!');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(0, 0)).toContainText('0:Human: Hi!');
|
||||||
await n8n.logs.setInputDisplayMode('schema');
|
await n8n.canvas.logsPanel.inputPanel.switchDisplayMode('schema');
|
||||||
await expect(n8n.logs.getInputPanel()).toContainText('messages[0]');
|
await expect(n8n.canvas.logsPanel.inputPanel.get()).toContainText('messages[0]');
|
||||||
await expect(n8n.logs.getInputPanel()).toContainText('Human: Hi!');
|
await expect(n8n.canvas.logsPanel.inputPanel.get()).toContainText('Human: Hi!');
|
||||||
await n8n.logs.setInputDisplayMode('json');
|
await n8n.canvas.logsPanel.inputPanel.switchDisplayMode('json');
|
||||||
await expect(n8n.logs.getInputPanel()).toContainText('[{"messages": ["Human: Hi!"],');
|
await expect(n8n.canvas.logsPanel.inputPanel.get()).toContainText(
|
||||||
|
'[{"messages": ["Human: Hi!"],',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should show input and output data of correct run index and branch', async ({
|
test('should show input and output data of correct run index and branch', async ({
|
||||||
@@ -130,48 +142,49 @@ test.describe('Logs', () => {
|
|||||||
await setupRequirements({ workflow: 'Workflow_if.json' });
|
await setupRequirements({ workflow: 'Workflow_if.json' });
|
||||||
|
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
await n8n.canvas.clickExecuteWorkflowButton();
|
await n8n.canvas.clickExecuteWorkflowButton();
|
||||||
|
|
||||||
await n8n.logs.clickLogEntryAtRow(2); // Run #1 of 'Edit Fields' node; input is 'Code' node
|
await n8n.canvas.logsPanel.clickLogEntryAtRow(2); // Run #1 of 'Edit Fields' node; input is 'Code' node
|
||||||
await n8n.logs.toggleInputPanel();
|
await n8n.canvas.logsPanel.toggleInputPanel();
|
||||||
await n8n.logs.setInputDisplayMode('table');
|
await n8n.canvas.logsPanel.inputPanel.get().hover();
|
||||||
await expect(n8n.logs.getInputTableRows()).toHaveCount(11);
|
await n8n.canvas.logsPanel.inputPanel.switchDisplayMode('table');
|
||||||
await expect(n8n.logs.getInputTbodyCell(0, 0)).toContainText('0');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTableRows()).toHaveCount(11);
|
||||||
await expect(n8n.logs.getInputTbodyCell(9, 0)).toContainText('9');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(0, 0)).toContainText('0');
|
||||||
await n8n.logs.clickOpenNdvAtRow(2);
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(9, 0)).toContainText('9');
|
||||||
await n8n.ndv.switchInputMode('Table');
|
await n8n.canvas.logsPanel.clickOpenNdvAtRow(2);
|
||||||
|
await n8n.ndv.inputPanel.switchDisplayMode('table');
|
||||||
await expect(n8n.ndv.getInputSelect()).toHaveValue(`${NODES.CODE} `);
|
await expect(n8n.ndv.getInputSelect()).toHaveValue(`${NODES.CODE} `);
|
||||||
await expect(n8n.ndv.getInputTableRows()).toHaveCount(11);
|
await expect(n8n.ndv.inputPanel.getTableRows()).toHaveCount(11);
|
||||||
await expect(n8n.ndv.getInputTbodyCell(0, 0)).toContainText('0');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(0, 0)).toContainText('0');
|
||||||
await expect(n8n.ndv.getInputTbodyCell(9, 0)).toContainText('9');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(9, 0)).toContainText('9');
|
||||||
await expect(n8n.ndv.getOutputRunSelectorInput()).toHaveValue('1 of 3 (10 items)');
|
await expect(n8n.ndv.outputPanel.getRunSelectorInput()).toHaveValue('1 of 3 (10 items)');
|
||||||
|
|
||||||
await n8n.ndv.clickBackToCanvasButton();
|
await n8n.ndv.clickBackToCanvasButton();
|
||||||
|
|
||||||
await n8n.logs.clickLogEntryAtRow(4); // Run #2 of 'Edit Fields' node; input is false branch of 'If' node
|
await n8n.canvas.logsPanel.clickLogEntryAtRow(4); // Run #2 of 'Edit Fields' node; input is false branch of 'If' node
|
||||||
await expect(n8n.logs.getInputTableRows()).toHaveCount(6);
|
await expect(n8n.canvas.logsPanel.inputPanel.getTableRows()).toHaveCount(6);
|
||||||
await expect(n8n.logs.getInputTbodyCell(0, 0)).toContainText('5');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(0, 0)).toContainText('5');
|
||||||
await expect(n8n.logs.getInputTbodyCell(4, 0)).toContainText('9');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(4, 0)).toContainText('9');
|
||||||
await n8n.logs.clickOpenNdvAtRow(4);
|
await n8n.canvas.logsPanel.clickOpenNdvAtRow(4);
|
||||||
await expect(n8n.ndv.getInputSelect()).toHaveValue(`${NODES.IF} `);
|
await expect(n8n.ndv.getInputSelect()).toHaveValue(`${NODES.IF} `);
|
||||||
await expect(n8n.ndv.getInputTableRows()).toHaveCount(6);
|
await expect(n8n.ndv.inputPanel.getTableRows()).toHaveCount(6);
|
||||||
await expect(n8n.ndv.getInputTbodyCell(0, 0)).toContainText('5');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(0, 0)).toContainText('5');
|
||||||
await expect(n8n.ndv.getInputTbodyCell(4, 0)).toContainText('9');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(4, 0)).toContainText('9');
|
||||||
await expect(n8n.ndv.getOutputRunSelectorInput()).toHaveValue('2 of 3 (5 items)');
|
await expect(n8n.ndv.outputPanel.getRunSelectorInput()).toHaveValue('2 of 3 (5 items)');
|
||||||
|
|
||||||
await n8n.ndv.clickBackToCanvasButton();
|
await n8n.ndv.clickBackToCanvasButton();
|
||||||
|
|
||||||
await n8n.logs.clickLogEntryAtRow(5); // Run #3 of 'Edit Fields' node; input is true branch of 'If' node
|
await n8n.canvas.logsPanel.clickLogEntryAtRow(5); // Run #3 of 'Edit Fields' node; input is true branch of 'If' node
|
||||||
await expect(n8n.logs.getInputTableRows()).toHaveCount(6);
|
await expect(n8n.canvas.logsPanel.inputPanel.getTableRows()).toHaveCount(6);
|
||||||
await expect(n8n.logs.getInputTbodyCell(0, 0)).toContainText('0');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(0, 0)).toContainText('0');
|
||||||
await expect(n8n.logs.getInputTbodyCell(4, 0)).toContainText('4');
|
await expect(n8n.canvas.logsPanel.inputPanel.getTbodyCell(4, 0)).toContainText('4');
|
||||||
await n8n.logs.clickOpenNdvAtRow(5);
|
await n8n.canvas.logsPanel.clickOpenNdvAtRow(5);
|
||||||
await expect(n8n.ndv.getInputSelect()).toHaveValue(`${NODES.IF} `);
|
await expect(n8n.ndv.getInputSelect()).toHaveValue(`${NODES.IF} `);
|
||||||
await expect(n8n.ndv.getInputTableRows()).toHaveCount(6);
|
await expect(n8n.ndv.inputPanel.getTableRows()).toHaveCount(6);
|
||||||
await expect(n8n.ndv.getInputTbodyCell(0, 0)).toContainText('0');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(0, 0)).toContainText('0');
|
||||||
await expect(n8n.ndv.getInputTbodyCell(4, 0)).toContainText('4');
|
await expect(n8n.ndv.inputPanel.getTbodyCell(4, 0)).toContainText('4');
|
||||||
await expect(n8n.ndv.getOutputRunSelectorInput()).toHaveValue('3 of 3 (5 items)');
|
await expect(n8n.ndv.outputPanel.getRunSelectorInput()).toHaveValue('3 of 3 (5 items)');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should keep populated logs unchanged when workflow get edits after the execution', async ({
|
test('should keep populated logs unchanged when workflow get edits after the execution', async ({
|
||||||
@@ -181,14 +194,14 @@ test.describe('Logs', () => {
|
|||||||
await setupRequirements({ workflow: 'Workflow_if.json' });
|
await setupRequirements({ workflow: 'Workflow_if.json' });
|
||||||
|
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
|
|
||||||
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(6);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(6);
|
||||||
await n8n.canvas.nodeDisableButton(NODES.EDIT_FIELDS).click();
|
await n8n.canvas.nodeDisableButton(NODES.EDIT_FIELDS).click();
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(6);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(6);
|
||||||
await n8n.canvas.deleteNodeByName(NODES.IF);
|
await n8n.canvas.deleteNodeByName(NODES.IF);
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(6);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: make it possible to test workflows with AI model end-to-end
|
// TODO: make it possible to test workflows with AI model end-to-end
|
||||||
@@ -196,23 +209,25 @@ test.describe('Logs', () => {
|
|||||||
await setupRequirements({ workflow: 'Workflow_ai_agent.json' });
|
await setupRequirements({ workflow: 'Workflow_ai_agent.json' });
|
||||||
|
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
|
|
||||||
await n8n.canvas.sendManualChatMessage('Hi!');
|
await n8n.canvas.logsPanel.sendManualChatMessage('Hi!');
|
||||||
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
||||||
await n8n.canvas.openExecutions();
|
await n8n.canvas.openExecutions();
|
||||||
await n8n.executions.getAutoRefreshButton().click();
|
await n8n.executions.getAutoRefreshButton().click();
|
||||||
await expect(n8n.executions.getManualChatMessages().nth(0)).toContainText('Hi!');
|
await expect(n8n.executions.logsPanel.getManualChatMessages().nth(0)).toContainText('Hi!');
|
||||||
await expect(n8n.executions.getManualChatMessages().nth(1)).toContainText(
|
await expect(n8n.executions.logsPanel.getManualChatMessages().nth(1)).toContainText(
|
||||||
'Hello from e2e model!!!',
|
'Hello from e2e model!!!',
|
||||||
);
|
);
|
||||||
await expect(
|
await expect(
|
||||||
n8n.executions.getLogsOverviewStatus().filter({ hasText: /Success in [\d.]+m?s/ }),
|
n8n.executions.logsPanel.getOverviewStatus().filter({ hasText: /Success in [\d.]+m?s/ }),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
await expect(n8n.executions.getLogEntries()).toHaveCount(3);
|
await expect(n8n.executions.logsPanel.getLogEntries()).toHaveCount(3);
|
||||||
await expect(n8n.executions.getLogEntries().nth(0)).toContainText('When chat message received');
|
await expect(n8n.executions.logsPanel.getLogEntries().nth(0)).toContainText(
|
||||||
await expect(n8n.executions.getLogEntries().nth(1)).toContainText('AI Agent');
|
'When chat message received',
|
||||||
await expect(n8n.executions.getLogEntries().nth(2)).toContainText('E2E Chat Model');
|
);
|
||||||
|
await expect(n8n.executions.logsPanel.getLogEntries().nth(1)).toContainText('AI Agent');
|
||||||
|
await expect(n8n.executions.logsPanel.getLogEntries().nth(2)).toContainText('E2E Chat Model');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should show logs for a workflow with a node that waits for webhook', async ({
|
test('should show logs for a workflow with a node that waits for webhook', async ({
|
||||||
@@ -223,18 +238,21 @@ test.describe('Logs', () => {
|
|||||||
|
|
||||||
await n8n.canvas.canvasBody().click({ position: { x: 0, y: 0 } }); // click logs panel to deselect nodes in canvas
|
await n8n.canvas.canvasBody().click({ position: { x: 0, y: 0 } }); // click logs panel to deselect nodes in canvas
|
||||||
await n8n.canvas.clickZoomToFitButton();
|
await n8n.canvas.clickZoomToFitButton();
|
||||||
await n8n.logs.openLogsPanel();
|
await n8n.canvas.logsPanel.open();
|
||||||
|
|
||||||
await n8n.canvas.clickExecuteWorkflowButton();
|
await n8n.canvas.clickExecuteWorkflowButton();
|
||||||
|
|
||||||
await expect(n8n.canvas.getNodesWithSpinner()).toContainText(NODES.WAIT_NODE);
|
await expect(n8n.canvas.getNodesWithSpinner()).toContainText(NODES.WAIT_NODE);
|
||||||
await expect(n8n.canvas.getWaitingNodes()).toContainText(NODES.WAIT_NODE);
|
await expect(n8n.canvas.getWaitingNodes()).toContainText(NODES.WAIT_NODE);
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(2);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(2);
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText(NODES.WAIT_NODE);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText(NODES.WAIT_NODE);
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText('Waiting');
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText('Waiting');
|
||||||
|
|
||||||
await n8n.canvas.openNode(NODES.WAIT_NODE);
|
await n8n.canvas.openNode(NODES.WAIT_NODE);
|
||||||
const webhookUrl = await n8n.ndv.getOutputDataContainer().locator('a').getAttribute('href');
|
const webhookUrl = await n8n.ndv.outputPanel
|
||||||
|
.getDataContainer()
|
||||||
|
.locator('a')
|
||||||
|
.getAttribute('href');
|
||||||
await n8n.ndv.clickBackToCanvasButton();
|
await n8n.ndv.clickBackToCanvasButton();
|
||||||
|
|
||||||
// Trigger the webhook
|
// Trigger the webhook
|
||||||
@@ -244,11 +262,11 @@ test.describe('Logs', () => {
|
|||||||
await expect(n8n.canvas.getNodesWithSpinner()).not.toBeVisible();
|
await expect(n8n.canvas.getNodesWithSpinner()).not.toBeVisible();
|
||||||
await expect(n8n.canvas.getWaitingNodes()).not.toBeVisible();
|
await expect(n8n.canvas.getWaitingNodes()).not.toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
n8n.logs.getOverviewStatus().filter({ hasText: /Success in [\d.]+m?s/ }),
|
n8n.canvas.logsPanel.getOverviewStatus().filter({ hasText: /Success in [\d.]+m?s/ }),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
await n8n.logs.getLogEntries().nth(1).click(); // click selected row to deselect
|
await n8n.canvas.logsPanel.getLogEntries().nth(1).click(); // click selected row to deselect
|
||||||
await expect(n8n.logs.getLogEntries()).toHaveCount(2);
|
await expect(n8n.canvas.logsPanel.getLogEntries()).toHaveCount(2);
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText(NODES.WAIT_NODE);
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText(NODES.WAIT_NODE);
|
||||||
await expect(n8n.logs.getLogEntries().nth(1)).toContainText('Success');
|
await expect(n8n.canvas.logsPanel.getLogEntries().nth(1)).toContainText('Success');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ test.describe('AI-812-partial-execs-broken-when-using-chat-trigger', () => {
|
|||||||
|
|
||||||
test.afterEach(async ({ n8n }) => {
|
test.afterEach(async ({ n8n }) => {
|
||||||
await n8n.notifications.quickCloseAll();
|
await n8n.notifications.quickCloseAll();
|
||||||
await n8n.canvas.clearExecutionData();
|
await n8n.canvas.logsPanel.clearExecutionData();
|
||||||
await n8n.canvas.sendManualChatMessage('Test Full Execution');
|
await n8n.canvas.logsPanel.sendManualChatMessage('Test Full Execution');
|
||||||
|
|
||||||
await expect(n8n.canvas.getManualChatMessages()).toHaveCount(4);
|
await expect(n8n.canvas.logsPanel.getManualChatMessages()).toHaveCount(4);
|
||||||
|
|
||||||
await expect(n8n.canvas.getManualChatMessages().last()).toContainText(
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().last()).toContainText(
|
||||||
'Set 3 with chatInput: Test Full Execution',
|
'Set 3 with chatInput: Test Full Execution',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -26,14 +26,14 @@ test.describe('AI-812-partial-execs-broken-when-using-chat-trigger', () => {
|
|||||||
await n8n.canvas.openNode('Edit Fields1');
|
await n8n.canvas.openNode('Edit Fields1');
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
|
|
||||||
await expect(n8n.canvas.getManualChatModal()).toBeVisible();
|
await expect(n8n.canvas.logsPanel.getManualChatModal()).toBeVisible();
|
||||||
await n8n.canvas.sendManualChatMessage('Test Partial Execution');
|
await n8n.canvas.logsPanel.sendManualChatMessage('Test Partial Execution');
|
||||||
|
|
||||||
await expect(n8n.canvas.getManualChatMessages()).toHaveCount(2);
|
await expect(n8n.canvas.logsPanel.getManualChatMessages()).toHaveCount(2);
|
||||||
await expect(n8n.canvas.getManualChatMessages().first()).toContainText(
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().first()).toContainText(
|
||||||
'Test Partial Execution',
|
'Test Partial Execution',
|
||||||
);
|
);
|
||||||
await expect(n8n.canvas.getManualChatMessages().last()).toContainText(
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().last()).toContainText(
|
||||||
'Set 2 with chatInput: Test Partial Execution',
|
'Set 2 with chatInput: Test Partial Execution',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -43,14 +43,14 @@ test.describe('AI-812-partial-execs-broken-when-using-chat-trigger', () => {
|
|||||||
}) => {
|
}) => {
|
||||||
await n8n.canvas.executeNodeFromContextMenu('Edit Fields');
|
await n8n.canvas.executeNodeFromContextMenu('Edit Fields');
|
||||||
|
|
||||||
await expect(n8n.canvas.getManualChatModal()).toBeVisible();
|
await expect(n8n.canvas.logsPanel.getManualChatModal()).toBeVisible();
|
||||||
await n8n.canvas.sendManualChatMessage('Test Partial Execution');
|
await n8n.canvas.logsPanel.sendManualChatMessage('Test Partial Execution');
|
||||||
|
|
||||||
await expect(n8n.canvas.getManualChatMessages()).toHaveCount(2);
|
await expect(n8n.canvas.logsPanel.getManualChatMessages()).toHaveCount(2);
|
||||||
await expect(n8n.canvas.getManualChatMessages().first()).toContainText(
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().first()).toContainText(
|
||||||
'Test Partial Execution',
|
'Test Partial Execution',
|
||||||
);
|
);
|
||||||
await expect(n8n.canvas.getManualChatMessages().last()).toContainText(
|
await expect(n8n.canvas.logsPanel.getManualChatMessages().last()).toContainText(
|
||||||
'Set 1 with chatInput: Test Partial Execution',
|
'Set 1 with chatInput: Test Partial Execution',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ test.describe('Proxy server @capability:proxy', () => {
|
|||||||
// Execute workflow - this should now proxy through mockserver
|
// Execute workflow - this should now proxy through mockserver
|
||||||
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
|
||||||
await n8n.canvas.openNode('HTTP Request');
|
await n8n.canvas.openNode('HTTP Request');
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('Hello from ProxyServer!');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toContainText('Hello from ProxyServer!');
|
||||||
|
|
||||||
// Verify the request was handled by mockserver
|
// Verify the request was handled by mockserver
|
||||||
expect(
|
expect(
|
||||||
@@ -70,6 +70,6 @@ test.describe('Proxy server @capability:proxy', () => {
|
|||||||
await n8n.canvas.openNode('HTTP Request');
|
await n8n.canvas.openNode('HTTP Request');
|
||||||
await n8n.ndv.setParameterInput('url', 'https://jsonplaceholder.typicode.com/todos/1');
|
await n8n.ndv.setParameterInput('url', 'https://jsonplaceholder.typicode.com/todos/1');
|
||||||
await n8n.ndv.execute();
|
await n8n.ndv.execute();
|
||||||
await expect(n8n.ndv.getOutputTbodyCell(0, 0)).toContainText('1');
|
await expect(n8n.ndv.outputPanel.getTbodyCell(0, 0)).toContainText('1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user