mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-26 21:19:43 -08:00
6a5830959f
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
340 lines
16 KiB
TypeScript
340 lines
16 KiB
TypeScript
import { BasePage } from './base';
|
|
import { getVisiblePopper, getVisibleSelect } from '../utils';
|
|
|
|
export class NDV extends BasePage {
|
|
getters = {
|
|
container: () => cy.getByTestId('ndv'),
|
|
backToCanvas: () => cy.getByTestId('back-to-canvas'),
|
|
copyInput: () => cy.getByTestId('copy-input'),
|
|
credentialInput: (eq = 0) => cy.getByTestId('node-credentials-select').eq(eq),
|
|
nodeExecuteButton: () => cy.getByTestId('node-execute-button'),
|
|
triggerPanelExecuteButton: () => cy.getByTestId('trigger-execute-button'),
|
|
inputSelect: () => cy.getByTestId('ndv-input-select'),
|
|
inputOption: () => cy.getByTestId('ndv-input-option'),
|
|
inputPanel: () => cy.getByTestId('ndv-input-panel'),
|
|
outputPanel: () => cy.getByTestId('output-panel'),
|
|
executingLoader: () => cy.getByTestId('ndv-executing'),
|
|
inputDataContainer: () => this.getters.inputPanel().findChildByTestId('ndv-data-container'),
|
|
inputDisplayMode: () =>
|
|
this.getters.inputPanel().findChildByTestId('ndv-run-data-display-mode').first(),
|
|
outputDataContainer: () => this.getters.outputPanel().findChildByTestId('ndv-data-container'),
|
|
outputDisplayMode: () =>
|
|
this.getters.outputPanel().findChildByTestId('ndv-run-data-display-mode').first(),
|
|
pinDataButton: () => this.getters.outputPanel().findChildByTestId('ndv-pin-data'),
|
|
unpinDataLink: () => this.getters.outputPanel().findChildByTestId('ndv-unpin-data'),
|
|
editPinnedDataButton: () => cy.getByTestId('ndv-edit-pinned-data'),
|
|
pinnedDataEditor: () => this.getters.outputPanel().find('.cm-editor .cm-scroller .cm-content'),
|
|
runDataPaneHeader: () => cy.getByTestId('run-data-pane-header'),
|
|
aiOutputModeToggle: () => cy.getByTestId('ai-output-mode-select'),
|
|
nodeOutputHint: () => cy.getByTestId('ndv-output-run-node-hint'),
|
|
savePinnedDataButton: () =>
|
|
this.getters.runDataPaneHeader().find('button').filter(':visible').contains('Save'),
|
|
inputLabel: () => cy.getByTestId('input-label'),
|
|
outputTableRows: () => this.getters.outputDataContainer().find('table tr'),
|
|
outputTableHeaders: () => this.getters.outputDataContainer().find('table thead th'),
|
|
outputTableHeaderByText: (text: string) => this.getters.outputTableHeaders().contains(text),
|
|
outputTableRow: (row: number) => this.getters.outputTableRows().eq(row),
|
|
outputTbodyCell: (row: number, col: number) =>
|
|
this.getters.outputTableRow(row).find('td').eq(col),
|
|
inputTableRows: () => this.getters.inputDataContainer().find('table tr'),
|
|
inputTableHeaders: () => this.getters.inputDataContainer().find('table thead th'),
|
|
inputTableRow: (row: number) => this.getters.inputTableRows().eq(row),
|
|
inputTbodyCell: (row: number, col: number) =>
|
|
this.getters.inputTableRow(row).find('td').eq(col),
|
|
inlineExpressionEditorInput: () => cy.getByTestId('inline-expression-editor-input'),
|
|
inlineExpressionEditorOutput: () => cy.getByTestId('inline-expression-editor-output'),
|
|
inlineExpressionEditorItemInput: () =>
|
|
cy.getByTestId('inline-expression-editor-item-input').find('input'),
|
|
inlineExpressionEditorItemPrevButton: () =>
|
|
cy.getByTestId('inline-expression-editor-item-prev'),
|
|
inlineExpressionEditorItemNextButton: () =>
|
|
cy.getByTestId('inline-expression-editor-item-next'),
|
|
nodeParameters: () => cy.getByTestId('node-parameters'),
|
|
parameterInput: (parameterName: string) => cy.getByTestId(`parameter-input-${parameterName}`),
|
|
parameterInputIssues: (parameterName: string) =>
|
|
cy
|
|
.getByTestId(`parameter-input-${parameterName}`)
|
|
.should('have.length', 1)
|
|
.findChildByTestId('parameter-issues'),
|
|
parameterExpressionPreview: (parameterName: string) =>
|
|
this.getters
|
|
.nodeParameters()
|
|
.find(`[data-test-id="parameter-expression-preview-${parameterName}"]`),
|
|
nodeNameContainer: () => cy.getByTestId('node-title-container'),
|
|
nodeRenameInput: () => cy.getByTestId('node-rename-input'),
|
|
executePrevious: () => cy.getByTestId('execute-previous-node'),
|
|
httpRequestNotice: () => cy.getByTestId('node-parameters-http-notice'),
|
|
nodeCredentialsLabel: () => cy.getByTestId('credentials-label'),
|
|
nthParam: (n: number) => cy.getByTestId('node-parameters').find('.parameter-item').eq(n),
|
|
inputRunSelector: () => this.getters.inputPanel().findChildByTestId('run-selector'),
|
|
inputLinkRun: () => this.getters.inputPanel().findChildByTestId('link-run'),
|
|
outputRunSelector: () => this.getters.outputPanel().findChildByTestId('run-selector'),
|
|
outputLinkRun: () => this.getters.outputPanel().findChildByTestId('link-run'),
|
|
outputHoveringItem: () => this.getters.outputPanel().findChildByTestId('hovering-item'),
|
|
inputHoveringItem: () => this.getters.inputPanel().findChildByTestId('hovering-item'),
|
|
outputBranches: () => this.getters.outputPanel().findChildByTestId('branches'),
|
|
inputBranches: () => this.getters.inputPanel().findChildByTestId('branches'),
|
|
resourceLocator: (paramName: string) => cy.getByTestId(`resource-locator-${paramName}`),
|
|
resourceLocatorInput: (paramName: string) =>
|
|
this.getters.resourceLocator(paramName).find('[data-test-id="rlc-input-container"]'),
|
|
resourceLocatorDropdown: (paramName: string) =>
|
|
this.getters.resourceLocator(paramName).find('[data-test-id="resource-locator-dropdown"]'),
|
|
resourceLocatorErrorMessage: () => cy.getByTestId('rlc-error-container'),
|
|
resourceLocatorAddCredentials: () => this.getters.resourceLocatorErrorMessage().find('a'),
|
|
resourceLocatorModeSelector: (paramName: string) =>
|
|
this.getters.resourceLocator(paramName).find('[data-test-id="rlc-mode-selector"]'),
|
|
resourceLocatorSearch: (paramName: string) =>
|
|
this.getters.resourceLocator(paramName).findChildByTestId('rlc-search'),
|
|
resourceMapperFieldsContainer: () => cy.getByTestId('mapping-fields-container'),
|
|
resourceMapperSelectColumn: () => cy.getByTestId('matching-column-select'),
|
|
resourceMapperRemoveFieldButton: (fieldName: string) =>
|
|
cy.getByTestId(`remove-field-button-${fieldName}`),
|
|
resourceMapperColumnsOptionsButton: () =>
|
|
cy.getByTestId('columns-parameter-input-options-container'),
|
|
resourceMapperRemoveAllFieldsOption: () => cy.getByTestId('action-removeAllFields'),
|
|
sqlEditorContainer: () => cy.getByTestId('sql-editor-container'),
|
|
htmlEditorContainer: () => cy.getByTestId('html-editor-container'),
|
|
filterComponent: (paramName: string) => cy.getByTestId(`filter-${paramName}`),
|
|
filterCombinator: (paramName: string, index = 0) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-combinator-select').eq(index),
|
|
filterConditions: (paramName: string) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-condition'),
|
|
filterCondition: (paramName: string, index = 0) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-condition').eq(index),
|
|
filterConditionLeft: (paramName: string, index = 0) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-condition-left').eq(index),
|
|
filterConditionRight: (paramName: string, index = 0) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-condition-right').eq(index),
|
|
filterConditionOperator: (paramName: string, index = 0) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-operator-select').eq(index),
|
|
filterConditionRemove: (paramName: string, index = 0) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-remove-condition').eq(index),
|
|
filterConditionAdd: (paramName: string) =>
|
|
this.getters.filterComponent(paramName).getByTestId('filter-add-condition'),
|
|
assignmentCollection: (paramName: string) =>
|
|
cy.getByTestId(`assignment-collection-${paramName}`),
|
|
assignmentCollectionAdd: (paramName: string) =>
|
|
this.getters.assignmentCollection(paramName).getByTestId('assignment-collection-drop-area'),
|
|
assignment: (paramName: string, index = 0) =>
|
|
this.getters.assignmentCollection(paramName).getByTestId('assignment').eq(index),
|
|
assignmentRemove: (paramName: string, index = 0) =>
|
|
this.getters.assignment(paramName, index).getByTestId('assignment-remove'),
|
|
assignmentName: (paramName: string, index = 0) =>
|
|
this.getters.assignment(paramName, index).getByTestId('assignment-name'),
|
|
assignmentValue: (paramName: string, index = 0) =>
|
|
this.getters.assignment(paramName, index).getByTestId('assignment-value'),
|
|
assignmentType: (paramName: string, index = 0) =>
|
|
this.getters.assignment(paramName, index).getByTestId('assignment-type-select'),
|
|
searchInput: () => cy.getByTestId('ndv-search'),
|
|
pagination: () => cy.getByTestId('ndv-data-pagination'),
|
|
nodeVersion: () => cy.getByTestId('node-version'),
|
|
nodeSettingsTab: () => cy.getByTestId('tab-settings'),
|
|
codeEditorFullscreenButton: () => cy.getByTestId('code-editor-fullscreen-button'),
|
|
codeEditorDialog: () => cy.getByTestId('code-editor-fullscreen'),
|
|
codeEditorFullscreen: () => this.getters.codeEditorDialog().find('.cm-content'),
|
|
nodeRunTooltipIndicator: () => cy.getByTestId('node-run-info'),
|
|
nodeRunSuccessIndicator: () => cy.getByTestId('node-run-status-success'),
|
|
nodeRunErrorIndicator: () => cy.getByTestId('node-run-status-danger'),
|
|
nodeRunErrorMessage: () => cy.getByTestId('node-error-message'),
|
|
nodeRunErrorDescription: () => cy.getByTestId('node-error-description'),
|
|
fixedCollectionParameter: (paramName: string) =>
|
|
cy.getByTestId(`fixed-collection-${paramName}`),
|
|
schemaViewNode: () => cy.getByTestId('run-data-schema-node'),
|
|
schemaViewNodeName: () => cy.getByTestId('run-data-schema-node-name'),
|
|
expressionExpanders: () => cy.getByTestId('expander'),
|
|
expressionModalOutput: () => cy.getByTestId('expression-modal-output'),
|
|
};
|
|
|
|
actions = {
|
|
pinData: () => {
|
|
this.getters.pinDataButton().click({ force: true });
|
|
},
|
|
unPinData: () => {
|
|
this.getters.unpinDataLink().click({ force: true });
|
|
},
|
|
editPinnedData: () => {
|
|
this.getters.editPinnedDataButton().click();
|
|
},
|
|
savePinnedData: () => {
|
|
this.getters.savePinnedDataButton().click();
|
|
},
|
|
execute: () => {
|
|
this.getters.nodeExecuteButton().first().click();
|
|
},
|
|
close: () => {
|
|
this.getters.backToCanvas().click({ force: true });
|
|
},
|
|
openInlineExpressionEditor: () => {
|
|
cy.contains('Expression').invoke('show').click();
|
|
this.getters.inlineExpressionEditorInput().click();
|
|
},
|
|
setPinnedData: (data: object | string) => {
|
|
const pinnedData = typeof data === 'string' ? data : JSON.stringify(data);
|
|
this.getters.editPinnedDataButton().click();
|
|
|
|
this.getters.pinnedDataEditor().click();
|
|
this.getters
|
|
.pinnedDataEditor()
|
|
.type(`{selectall}{backspace}${pinnedData.replace(new RegExp('{', 'g'), '{{}')}`);
|
|
|
|
this.actions.savePinnedData();
|
|
},
|
|
pastePinnedData: (data: object) => {
|
|
this.getters.editPinnedDataButton().click();
|
|
|
|
this.getters.pinnedDataEditor().click();
|
|
this.getters.pinnedDataEditor().invoke('text', '').paste(JSON.stringify(data));
|
|
|
|
this.actions.savePinnedData();
|
|
},
|
|
clearParameterInput: (parameterName: string) => {
|
|
this.getters.parameterInput(parameterName).type('{selectall}{backspace}');
|
|
},
|
|
typeIntoParameterInput: (
|
|
parameterName: string,
|
|
content: string,
|
|
opts?: { parseSpecialCharSequences: boolean },
|
|
) => {
|
|
this.getters.parameterInput(parameterName).type(content, opts);
|
|
},
|
|
selectOptionInParameterDropdown: (_: string, content: string) => {
|
|
getVisibleSelect().find('.option-headline').contains(content).click();
|
|
},
|
|
rename: (newName: string) => {
|
|
this.getters.nodeNameContainer().click();
|
|
this.getters.nodeRenameInput().should('be.visible').type('{selectall}').type(newName);
|
|
cy.get('body').type('{enter}');
|
|
},
|
|
executePrevious: () => {
|
|
this.getters.executePrevious().click({ force: true });
|
|
},
|
|
mapDataFromHeader: (col: number, parameterName: string) => {
|
|
const draggable = `[data-test-id="ndv-input-panel"] [data-test-id="ndv-data-container"] table th:nth-child(${col})`;
|
|
const droppable = `[data-test-id="parameter-input-${parameterName}"]`;
|
|
cy.draganddrop(draggable, droppable);
|
|
},
|
|
mapToParameter: (parameterName: string, position?: 'top' | 'center' | 'bottom') => {
|
|
const droppable = `[data-test-id="parameter-input-${parameterName}"]`;
|
|
cy.draganddrop('', droppable, { position });
|
|
},
|
|
switchInputMode: (type: 'Schema' | 'Table' | 'JSON' | 'Binary') => {
|
|
this.getters.inputDisplayMode().find('label').contains(type).click({ force: true });
|
|
},
|
|
switchOutputMode: (type: 'Schema' | 'Table' | 'JSON' | 'Binary') => {
|
|
this.getters.outputDisplayMode().find('label').contains(type).click({ force: true });
|
|
},
|
|
selectInputNode: (nodeName: string) => {
|
|
this.getters.inputSelect().find('.el-select').click();
|
|
this.getters.inputOption().contains(nodeName).click();
|
|
},
|
|
addDefaultPinnedData: () => {
|
|
this.actions.editPinnedData();
|
|
this.actions.savePinnedData();
|
|
},
|
|
changeInputRunSelector: (runName: string) => {
|
|
this.getters.inputRunSelector().click();
|
|
getVisibleSelect().find('.el-select-dropdown__item').contains(runName).click();
|
|
},
|
|
changeOutputRunSelector: (runName: string) => {
|
|
this.getters.outputRunSelector().click();
|
|
getVisibleSelect().find('.el-select-dropdown__item').contains(runName).click();
|
|
},
|
|
toggleOutputRunLinking: () => {
|
|
this.getters.outputLinkRun().click();
|
|
},
|
|
toggleInputRunLinking: () => {
|
|
this.getters.inputLinkRun().click();
|
|
},
|
|
switchOutputBranch: (name: string) => {
|
|
this.getters.outputBranches().get('span').contains(name).click();
|
|
},
|
|
switchInputBranch: (name: string) => {
|
|
this.getters.inputBranches().get('span').contains(name).click();
|
|
},
|
|
setRLCValue: (paramName: string, value: string) => {
|
|
this.getters.resourceLocatorModeSelector(paramName).click();
|
|
getVisibleSelect().find('li').last().click();
|
|
this.getters.resourceLocatorInput(paramName).type(value);
|
|
},
|
|
validateExpressionPreview: (paramName: string, value: string) => {
|
|
this.getters
|
|
.parameterExpressionPreview(paramName)
|
|
.find('span')
|
|
.should('include.html', asEncodedHTML(value));
|
|
},
|
|
refreshResourceMapperColumns: () => {
|
|
this.getters.resourceMapperSelectColumn().realHover();
|
|
this.getters
|
|
.resourceMapperSelectColumn()
|
|
.findChildByTestId('action-toggle')
|
|
.should('have.length', 1)
|
|
.click();
|
|
|
|
getVisiblePopper().find('li').last().click();
|
|
},
|
|
addFilterCondition: (paramName: string) => {
|
|
this.getters.filterConditionAdd(paramName).click({ force: true });
|
|
},
|
|
removeFilterCondition: (paramName: string, index: number) => {
|
|
this.getters.filterConditionRemove(paramName, index).click();
|
|
},
|
|
removeAssignment: (paramName: string, index: number) => {
|
|
this.getters.assignmentRemove(paramName, index).click();
|
|
},
|
|
setInvalidExpression: ({
|
|
fieldName,
|
|
invalidExpression,
|
|
}: {
|
|
fieldName: string;
|
|
invalidExpression?: string;
|
|
}) => {
|
|
this.actions.typeIntoParameterInput(fieldName, '=');
|
|
this.actions.typeIntoParameterInput(fieldName, invalidExpression ?? "{{ $('unknown')", {
|
|
parseSpecialCharSequences: false,
|
|
});
|
|
this.actions.validateExpressionPreview(fieldName, "node doesn't exist");
|
|
},
|
|
openSettings: () => {
|
|
this.getters.nodeSettingsTab().click();
|
|
},
|
|
|
|
openCodeEditorFullscreen: () => {
|
|
this.getters.codeEditorFullscreenButton().click({ force: true });
|
|
},
|
|
changeNodeOperation: (operation: string) => {
|
|
this.getters.parameterInput('operation').click();
|
|
cy.get('.el-select-dropdown__item')
|
|
.contains(new RegExp(`^${operation}$`))
|
|
.click({ force: true });
|
|
this.getters.parameterInput('operation').find('input').should('have.value', operation);
|
|
},
|
|
expressionSelectItem: (index: number) => {
|
|
this.getters.inlineExpressionEditorItemInput().type(`{selectall}${index}`);
|
|
},
|
|
expressionSelectNextItem: () => {
|
|
this.getters.inlineExpressionEditorItemNextButton().click();
|
|
},
|
|
expressionSelectPrevItem: () => {
|
|
this.getters.inlineExpressionEditorItemPrevButton().click();
|
|
},
|
|
addItemToFixedCollection: (paramName: string) => {
|
|
this.getters.fixedCollectionParameter(paramName).getByTestId('fixed-collection-add').click();
|
|
},
|
|
dragMainPanelToLeft: () => {
|
|
cy.drag('[data-test-id=panel-drag-button]', [-1000, 0], { moveTwice: true });
|
|
},
|
|
dragMainPanelToRight: () => {
|
|
cy.drag('[data-test-id=panel-drag-button]', [1000, 0], { moveTwice: true });
|
|
},
|
|
};
|
|
}
|
|
|
|
function asEncodedHTML(str: string): string {
|
|
return String(str)
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/ /g, ' ');
|
|
}
|