Skip to content

Commit

Permalink
add e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mutdmour committed Nov 14, 2024
1 parent 5f491fb commit 40fd8b3
Show file tree
Hide file tree
Showing 10 changed files with 650 additions and 25 deletions.
29 changes: 29 additions & 0 deletions cypress/composables/executions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Getters
*/

export const getExecutionsSidebar = () => cy.getByTestId('executions-sidebar');

export const getWorkflowExecutionPreviewIframe = () => cy.getByTestId('workflow-preview-iframe');

export const getExecutionPreviewBody = () =>
getWorkflowExecutionPreviewIframe()
.its('0.contentDocument.body')
.then((el) => cy.wrap(el));

export const getExecutionPreviewBodyNodes = () =>
getExecutionPreviewBody().findChildByTestId('canvas-node');

export const getExecutionPreviewBodyNodesByName = (name: string) =>
getExecutionPreviewBody().findChildByTestId('canvas-node').filter(`[data-name="${name}"]`).eq(0);

export function getExecutionPreviewOutputPanelRelatedExecutionLink() {
return getExecutionPreviewBody().findChildByTestId('related-execution-link');
}

/**
* Actions
*/

export const openExecutionPreviewNode = (name: string) =>
getExecutionPreviewBodyNodesByName(name).dblclick();
33 changes: 33 additions & 0 deletions cypress/composables/ndv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,38 @@ export function getOutputTableRow(row: number) {
return getOutputTableRows().eq(row);
}

export function getOutputTableHeaders() {
return getOutputPanelDataContainer().find('table thead th');
}

export function getOutputTableHeaderByText(text: string) {
return getOutputTableHeaders().contains(text);
}

export function getOutputTbodyCell(row: number, col: number) {
return getOutputTableRows().eq(row).find('td').eq(col);
}

export function getOutputRunSelector() {
return getOutputPanel().findChildByTestId('run-selector');
}

export function getOutputRunSelectorInput() {
return getOutputRunSelector().find('input');
}

export function getOutputPanelTable() {
return getOutputPanelDataContainer().get('table');
}

export function getOutputPanelItemsCount() {
return getOutputPanel().getByTestId('ndv-items-count');
}

export function getOutputPanelRelatedExecutionLink() {
return getOutputPanel().getByTestId('related-execution-link');
}

/**
* Actions
*/
Expand Down Expand Up @@ -90,3 +118,8 @@ export function setParameterSelectByContent(name: string, content: string) {
getParameterInputByName(name).realClick();
getVisibleSelect().find('.option-headline').contains(content).click();
}

export function changeOutputRunSelector(runName: string) {
getOutputRunSelector().click();
getVisibleSelect().find('.el-select-dropdown__item').contains(runName).click();
}
24 changes: 24 additions & 0 deletions cypress/composables/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ export function getCanvasNodes() {
);
}

export function getSaveButton() {
return cy.getByTestId('workflow-save-button');
}

export function getZoomToFitButton() {
return cy.getByTestId('zoom-to-fit');
}

/**
* Actions
*/
Expand Down Expand Up @@ -170,3 +178,19 @@ export function clickManualChatButton() {
export function openNode(nodeName: string) {
getNodeByName(nodeName).dblclick();
}

export function saveWorkflowOnButtonClick() {
cy.intercept('POST', '/rest/workflows').as('createWorkflow');
getSaveButton().should('contain', 'Save');
getSaveButton().click();
getSaveButton().should('contain', 'Saved');
cy.url().should('not.have.string', '/new');
}

export function pasteWorkflow(workflow: object) {
cy.get('body').paste(JSON.stringify(workflow));
}

export function clickZoomToFit() {
getZoomToFitButton().click();
}
140 changes: 140 additions & 0 deletions cypress/e2e/47-subworkflow-debugging.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import {
getExecutionPreviewOutputPanelRelatedExecutionLink,
getExecutionsSidebar,
getWorkflowExecutionPreviewIframe,
openExecutionPreviewNode,
} from '../composables/executions';
import {
changeOutputRunSelector,
getOutputPanelItemsCount,
getOutputPanelRelatedExecutionLink,
getOutputRunSelectorInput,
getOutputTableHeaders,
getOutputTableRows,
getOutputTbodyCell,
} from '../composables/ndv';
import {
clickExecuteWorkflowButton,
clickZoomToFit,
getCanvasNodes,
navigateToNewWorkflowPage,
openNode,
pasteWorkflow,
saveWorkflowOnButtonClick,
} from '../composables/workflow';
import SUBWORKFLOW_DEBUGGING_EXAMPLE from '../fixtures/Subworkflow-debugging-execute-workflow.json';

describe('Subworkflow debugging', () => {
beforeEach(() => {
navigateToNewWorkflowPage();
pasteWorkflow(SUBWORKFLOW_DEBUGGING_EXAMPLE);
saveWorkflowOnButtonClick();
getCanvasNodes().should('have.length', 11);
clickZoomToFit();

clickExecuteWorkflowButton();
});

describe('can inspect sub executed workflow', () => {
it('(Run once with all items/ Wait for Sub-workflow completion) (default behavior)', () => {
openNode('Execute Workflow with param');

getOutputPanelItemsCount().should('contain.text', '2 items, 1 sub-execution');
getOutputPanelRelatedExecutionLink().should('contain.text', 'Inspect Sub-Execution');
getOutputPanelRelatedExecutionLink().should('have.attr', 'href');

// ensure workflow executed and waited on output
getOutputTableHeaders().should('have.length', 2);
getOutputTbodyCell(1, 0).should('have.text', 'world Natalie Moore');
});

it('(Run once for each item/ Wait for Sub-workflow completion)', () => {
openNode('Execute Workflow with param1');

getOutputPanelItemsCount().should('contain.text', '2 items, 2 sub-execution');
getOutputPanelRelatedExecutionLink().should('not.exist');

// ensure workflow executed and waited on output
getOutputTableHeaders().should('have.length', 3);
getOutputTbodyCell(1, 0).find('a').should('have.attr', 'href');
getOutputTbodyCell(1, 1).should('have.text', 'world Natalie Moore');
});

it('(Run once with all items/ Wait for Sub-workflow completion)', () => {
openNode('Execute Workflow with param2');

getOutputPanelItemsCount().should('not.exist');
getOutputPanelRelatedExecutionLink().should('contain.text', 'Inspect Sub-Execution');
getOutputPanelRelatedExecutionLink().should('have.attr', 'href');

// ensure workflow executed but returned same data as input
getOutputRunSelectorInput().should('have.value', '2 of 2 (3 items, 1 sub-execution)');
getOutputTableHeaders().should('have.length', 6);
getOutputTableHeaders().eq(0).should('have.text', 'uid');
getOutputTableRows().should('have.length', 4);
getOutputTbodyCell(1, 1).should('include.text', '[email protected]');

changeOutputRunSelector('1 of 2 (2 items, 1 sub-execution)');
getOutputRunSelectorInput().should('have.value', '1 of 2 (2 items, 1 sub-execution)');
getOutputTableHeaders().should('have.length', 6);
getOutputTableHeaders().eq(0).should('have.text', 'uid');
getOutputTableRows().should('have.length', 3);
getOutputTbodyCell(1, 1).should('include.text', '[email protected]');
});

it('(Run once for each item/ Wait for Sub-workflow completion)', () => {
openNode('Execute Workflow with param3');

// ensure workflow executed but returned same data as input
getOutputRunSelectorInput().should('have.value', '2 of 2 (3 items, 3 sub-executions)');
getOutputTableHeaders().should('have.length', 7);
getOutputTableHeaders().eq(1).should('have.text', 'uid');
getOutputTableRows().should('have.length', 4);
getOutputTbodyCell(1, 0).find('a').should('have.attr', 'href');
getOutputTbodyCell(1, 2).should('include.text', '[email protected]');

changeOutputRunSelector('1 of 2 (2 items, 2 sub-executions)');
getOutputRunSelectorInput().should('have.value', '1 of 2 (2 items, 2 sub-executions)');
getOutputTableHeaders().should('have.length', 7);
getOutputTableHeaders().eq(1).should('have.text', 'uid');
getOutputTableRows().should('have.length', 3);

getOutputTbodyCell(1, 0).find('a').should('have.attr', 'href');
getOutputTbodyCell(1, 2).should('include.text', '[email protected]');
});
});

it('can inspect parent executions', () => {
cy.url().then((workflowUrl) => {
openNode('Execute Workflow with param');

getOutputPanelItemsCount().should('contain.text', '2 items, 1 sub-execution');
getOutputPanelRelatedExecutionLink().should('contain.text', 'Inspect Sub-Execution');
getOutputPanelRelatedExecutionLink().should('have.attr', 'href');

// ensure workflow executed and waited on output
getOutputTableHeaders().should('have.length', 2);
getOutputTbodyCell(1, 0).should('have.text', 'world Natalie Moore');

// cypress cannot handle new tabs so removing it
getOutputPanelRelatedExecutionLink().invoke('removeAttr', 'target').click();

getExecutionsSidebar().should('be.visible');
getWorkflowExecutionPreviewIframe().should('be.visible');
openExecutionPreviewNode('Execute Workflow Trigger');

getExecutionPreviewOutputPanelRelatedExecutionLink().should(
'include.text',
'Inspect Parent Execution',
);

getExecutionPreviewOutputPanelRelatedExecutionLink()
.invoke('removeAttr', 'target')
.click({ force: true });

cy.url().then((currentUrl) => {
expect(currentUrl === workflowUrl);
});
});
});
});
Loading

0 comments on commit 40fd8b3

Please sign in to comment.