refactor(editor): Add Workflows view e2e tests (#4573)

This commit is contained in:
OlegIvaniv
2022-11-11 09:07:14 +01:00
committed by GitHub
parent ed99aa2d59
commit 50f7538779
14 changed files with 287 additions and 11 deletions

View File

@@ -0,0 +1,84 @@
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from "../constants";
import { randFirstName, randLastName } from "@ngneat/falso";
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { v4 as uuid } from 'uuid';
const username = DEFAULT_USER_EMAIL;
const password = DEFAULT_USER_PASSWORD;
const firstName = randFirstName();
const lastName = randLastName();
const WorkflowsPage = new WorkflowsPageClass();
const WorkflowPage = new WorkflowPageClass();
describe('Workflows flow', () => {
beforeEach(() => {
cy.signup(username, firstName, lastName, password);
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('Not logged in');
return false;
})
cy.signin(username, password);
cy.visit(WorkflowsPage.url);
});
it('should create a new workflow using empty state card', () => {
WorkflowsPage.get('newWorkflowButtonCard').should('be.visible');
WorkflowsPage.get('newWorkflowButtonCard').click();
cy.createFixtureWorkflow('Test_workflow_1.json', `Empty State Card Workflow ${uuid()}`);
WorkflowPage.get('workflowTags').should('contain.text', 'some-tag-1');
WorkflowPage.get('workflowTags').should('contain.text', 'some-tag-2');
})
it('should create a new workflow using add workflow button', () => {
WorkflowsPage.get('newWorkflowButtonCard').should('not.exist');
WorkflowsPage.get('createWorkflowButton').click();
cy.createFixtureWorkflow('Test_workflow_2.json', `Add Workflow Button Workflow ${uuid()}`);
WorkflowPage.get('workflowTags').should('contain.text', 'other-tag-1');
WorkflowPage.get('workflowTags').should('contain.text', 'other-tag-2');
})
it('should search for a workflow', () => {
WorkflowsPage.get('searchBar').type('Empty State Card Workflow');
WorkflowsPage.get('workflowCards').should('have.length', 1);
WorkflowsPage.get('workflowCard', 'Empty State Card Workflow').should('contain.text', 'Empty State Card Workflow');
WorkflowsPage.get('searchBar').clear().type('Add Workflow Button Workflow');
WorkflowsPage.get('workflowCards').should('have.length', 1);
WorkflowsPage.get('workflowCard', 'Add Workflow Button Workflow').should('contain.text', 'Add Workflow Button Workflow');
WorkflowsPage.get('searchBar').clear().type('Some non-existent workflow');
WorkflowsPage.get('workflowCards').should('not.exist');
cy.contains('No workflows found').should('be.visible');
})
it('should delete all the workflows', () => {
WorkflowsPage.get('workflowCards').should('have.length', 2);
WorkflowsPage.get('workflowCards').each(($el) => {
const workflowName = $el.find('[data-test-id="workflow-card-name"]').text();
WorkflowsPage.get('workflowCardActions', workflowName).click();
WorkflowsPage.get('workflowDeleteButton').click();
cy.get('button').contains('delete').click();
})
WorkflowsPage.get('newWorkflowButtonCard').should('be.visible');
WorkflowsPage.get('newWorkflowTemplateCard').should('be.visible');
})
it('should contain empty state cards', () => {
WorkflowsPage.get('newWorkflowButtonCard').should('be.visible');
WorkflowsPage.get('newWorkflowTemplateCard').should('be.visible');
});
});

View File

@@ -0,0 +1,69 @@
{
"name": "Test workflow 1",
"nodes": [
{
"parameters": {},
"id": "a2f85497-260d-4489-a957-2b7d88e2f33d",
"name": "On clicking 'execute'",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
220,
260
]
},
{
"parameters": {
"jsCode": "// Loop over input items and add a new field\n// called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.myNewField = 1;\n}\n\nreturn $input.all();"
},
"id": "9493d278-1ede-47c9-bedf-92ac3a737c65",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [
400,
260
]
}
],
"pinData": {},
"connections": {
"On clicking 'execute'": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[]
]
}
},
"active": false,
"settings": {},
"hash": "a59c7b1c97b1741597afae0fcd43ebef",
"id": 3,
"meta": {
"instanceId": "a5280676597d00ecd0ea712da7f9cf2ce90174a791a309112731f6e44d162f35"
},
"tags": [
{
"name": "some-tag-1",
"createdAt": "2022-11-10T13:43:34.001Z",
"updatedAt": "2022-11-10T13:43:34.001Z",
"id": "6"
},
{
"name": "some-tag-2",
"createdAt": "2022-11-10T13:43:39.778Z",
"updatedAt": "2022-11-10T13:43:39.778Z",
"id": "7"
}
]
}

View File

@@ -0,0 +1,64 @@
{
"name": "Test workflow 2",
"nodes": [
{
"parameters": {},
"id": "624e0991-5dac-468b-b872-a9d35cb2c7d1",
"name": "On clicking 'execute'",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
360,
260
]
},
{
"parameters": {
"jsCode": "// Loop over input items and add a new field\n// called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.myNewField = 1;\n}\n\nreturn $input.all();"
},
"id": "48823b3a-ec82-4a05-84b8-24ac2747e648",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [
580,
260
]
}
],
"pinData": {},
"connections": {
"On clicking 'execute'": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {},
"hash": "4d2e29ffcae2a12bdd28a7abe9681a6b",
"id": 4,
"meta": {
"instanceId": "a5280676597d00ecd0ea712da7f9cf2ce90174a791a309112731f6e44d162f35"
},
"tags": [
{
"name": "other-tag-1",
"createdAt": "2022-11-10T13:45:43.821Z",
"updatedAt": "2022-11-10T13:45:43.821Z",
"id": "8"
},
{
"name": "other-tag-2",
"createdAt": "2022-11-10T13:45:46.881Z",
"updatedAt": "2022-11-10T13:45:46.881Z",
"id": "9"
}
]
}

11
cypress/pages/workflow.ts Normal file
View File

@@ -0,0 +1,11 @@
import { BasePage } from "./base";
export class WorkflowPage extends BasePage {
url = '/workflow/new';
elements = {
workflowNameInput: () => cy.getByTestId('workflow-name-input').then($el => cy.wrap($el.find('input'))),
workflowImportInput: () => cy.getByTestId('workflow-import-input'),
workflowTags: () => cy.getByTestId('workflow-tags'),
saveButton: () => cy.getByTestId('save-button'),
};
}

View File

@@ -2,5 +2,26 @@ import { BasePage } from "./base";
export class WorkflowsPage extends BasePage {
url = '/workflows';
elements = {}
elements = {
newWorkflowButtonCard: () => cy.getByTestId('new-workflow-card'),
newWorkflowTemplateCard: () => cy.getByTestId('new-workflow-template-card'),
searchBar: () => cy.getByTestId('resources-list-search'),
createWorkflowButton: () => cy.getByTestId('resources-list-add'),
workflowCards: () => cy.getByTestId(`workflow-card`),
workflowCard: (workflowName: string) => cy.getByTestId(`workflow-card`)
.contains(workflowName)
.parents('[data-test-id="workflow-card"]'),
workflowTags: (workflowName: string) => this.elements.workflowCard(workflowName)
.findChildByTestId('workflow-card-tags'),
workflowActivator: (workflowName: string) => this.elements.workflowCard(workflowName)
.findChildByTestId('workflow-card-activator'),
workflowActivatorStatus: (workflowName: string) => this.elements.workflowActivator(workflowName)
.findChildByTestId('workflow-activator-status'),
workflowCardActions: (workflowName: string) => this.elements.workflowCard(workflowName)
.findChildByTestId('workflow-card-actions'),
workflowDeleteButton: () => cy.getByTestId('action-toggle-dropdown').filter(':visible').contains('Delete')
// Not yet implemented
// myWorkflows: () => cy.getByTestId('my-workflows'),
// allWorkflows: () => cy.getByTestId('all-workflows'),
};
}

View File

@@ -26,12 +26,29 @@
import { WorkflowsPage, SigninPage, SignupPage } from "../pages";
import { N8N_AUTH_COOKIE } from "../constants";
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
Cypress.Commands.add('getByTestId', (selector, ...args) => {
return cy.get(`[data-test-id="${selector}"]`, ...args)
})
Cypress.Commands.add('createFixtureWorkflow', (fixtureKey, workflowName) => {
const WorkflowPage = new WorkflowPageClass()
// We need to force the click because the input is hidden
WorkflowPage.get('workflowImportInput').selectFile(`cypress/fixtures/${fixtureKey}`, { force: true});
WorkflowPage.get('workflowNameInput').should('be.disabled');
WorkflowPage.get('workflowNameInput').parent().click()
WorkflowPage.get('workflowNameInput').should('be.enabled');
WorkflowPage.get('workflowNameInput').clear().type(workflowName).type('{enter}');
WorkflowPage.get('saveButton').should('contain', 'Saved');
})
Cypress.Commands.add('findChildByTestId', { prevSubject: true }, (subject: Cypress.Chainable<JQuery<HTMLElement>>, childTestId) => {
return subject.find(`[data-test-id="${childTestId}"]`);
})
Cypress.Commands.add(
'signin',
(email, password) => {

View File

@@ -5,6 +5,8 @@ declare global {
namespace Cypress {
interface Chainable {
getByTestId(selector: string, ...args: (Partial<Loggable & Timeoutable & Withinable & Shadow> | undefined)[]): Chainable<JQuery<HTMLElement>>
findChildByTestId(childTestId: string): Chainable<JQuery<HTMLElement>>
createFixtureWorkflow(fixtureKey: string, workflowName: string): void;
signin(email: string, password: string): void;
signup(email: string, firstName: string, lastName: string, password: string): void;
}

View File

@@ -1,4 +1,4 @@
export type IE2ETestPageElement = (...args: unknown[]) =>
export type IE2ETestPageElement = (...args: any[]) =>
| Cypress.Chainable<JQuery<HTMLElement>>
| Cypress.Chainable<JQuery<HTMLButtonElement>>;