ci: Refactor e2e tests to be less flaky (no-changelog) (#9695)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2024-06-11 14:45:15 +02:00
committed by GitHub
parent bc35e8c33d
commit 3d0393c739
39 changed files with 485 additions and 539 deletions

View File

@@ -158,9 +158,7 @@ export class NDV extends BasePage {
this.getters.pinnedDataEditor().click();
this.getters
.pinnedDataEditor()
.type(`{selectall}{backspace}${pinnedData.replace(new RegExp('{', 'g'), '{{}')}`, {
delay: 0,
});
.type(`{selectall}{backspace}${pinnedData.replace(new RegExp('{', 'g'), '{{}')}`);
this.actions.savePinnedData();
},
@@ -168,10 +166,7 @@ export class NDV extends BasePage {
this.getters.editPinnedDataButton().click();
this.getters.pinnedDataEditor().click();
this.getters
.pinnedDataEditor()
.type('{selectall}{backspace}', { delay: 0 })
.paste(JSON.stringify(data));
this.getters.pinnedDataEditor().type('{selectall}{backspace}').paste(JSON.stringify(data));
this.actions.savePinnedData();
},
@@ -181,7 +176,7 @@ export class NDV extends BasePage {
typeIntoParameterInput: (
parameterName: string,
content: string,
opts?: { parseSpecialCharSequences: boolean; delay?: number },
opts?: { parseSpecialCharSequences: boolean },
) => {
this.getters.parameterInput(parameterName).type(content, opts);
},
@@ -272,16 +267,13 @@ export class NDV extends BasePage {
setInvalidExpression: ({
fieldName,
invalidExpression,
delay,
}: {
fieldName: string;
invalidExpression?: string;
delay?: number;
}) => {
this.actions.typeIntoParameterInput(fieldName, '=');
this.actions.typeIntoParameterInput(fieldName, invalidExpression ?? "{{ $('unknown')", {
parseSpecialCharSequences: false,
delay,
});
this.actions.validateExpressionPreview(fieldName, "node doesn't exist");
},

View File

@@ -30,6 +30,7 @@ export class PersonalSettingsPage extends BasePage {
this.getters.themeSelector().click();
this.getters.selectOptionsVisible().should('have.length', 3);
this.getters.selectOptionsVisible().contains(theme).click();
this.getters.saveSettingsButton().realClick();
},
loginAndVisit: (email: string, password: string) => {
cy.signin({ email, password });

View File

@@ -2,22 +2,6 @@ import * as formStep from '../composables/setup-template-form-step';
import { overrideFeatureFlag } from '../composables/featureFlags';
import { CredentialsModal, MessageBox } from './modals';
export type TemplateTestData = {
id: number;
fixture: string;
};
export const testData = {
simpleTemplate: {
id: 1205,
fixture: 'Test_Template_1.json',
},
templateWithoutCredentials: {
id: 1344,
fixture: 'Test_Template_2.json',
},
};
const credentialsModal = new CredentialsModal();
const messageBox = new MessageBox();

View File

@@ -1,41 +0,0 @@
import { BasePage } from './base';
export class TemplateWorkflowPage extends BasePage {
url = '/templates';
getters = {
useTemplateButton: () => cy.get('[data-test-id="use-template-button"]'),
description: () => cy.get('[data-test-id="template-description"]'),
};
actions = {
visit: (templateId: number) => {
cy.visit(`${this.url}/${templateId}`);
},
clickUseThisWorkflowButton: () => {
this.getters.useTemplateButton().click();
},
openTemplate: (
template: {
workflow: {
id: number;
name: string;
description: string;
user: { username: string };
image: Array<{ id: number; url: string }>;
};
},
templateHost: string,
) => {
cy.intercept('GET', `${templateHost}/api/templates/workflows/${template.workflow.id}`, {
statusCode: 200,
body: template,
}).as('getTemplate');
this.actions.visit(template.workflow.id);
cy.wait('@getTemplate');
},
};
}

View File

@@ -5,6 +5,7 @@ export class TemplatesPage extends BasePage {
getters = {
useTemplateButton: () => cy.getByTestId('use-template-button'),
description: () => cy.getByTestId('template-description'),
templateCards: () => cy.getByTestId('template-card'),
firstTemplateCard: () => this.getters.templateCards().first(),
allCategoriesFilter: () => cy.getByTestId('template-filter-all-categories'),
@@ -14,50 +15,30 @@ export class TemplatesPage extends BasePage {
collectionCountLabel: () => cy.getByTestId('collection-count-label'),
templateCountLabel: () => cy.getByTestId('template-count-label'),
templatesLoadingContainer: () => cy.getByTestId('templates-loading-container'),
expandCategoriesButton: () => cy.getByTestId('expand-categories-button'),
};
actions = {
openSingleTemplateView: (templateId: number) => {
cy.visit(`${this.url}/${templateId}`);
cy.waitForLoad();
},
openOnboardingFlow: (id: number, name: string, workflow: object, templatesHost: string) => {
const apiResponse = {
id,
name,
workflow,
};
openOnboardingFlow: () => {
cy.intercept('POST', '/rest/workflows').as('createWorkflow');
cy.intercept('GET', `${templatesHost}/api/workflows/templates/${id}`, {
statusCode: 200,
body: apiResponse,
}).as('getTemplate');
cy.intercept('GET', 'rest/workflows/**').as('getWorkflow');
cy.visit(`/workflows/onboarding/${id}`);
cy.visit('/workflows/onboarding/1');
cy.window().then((win) => {
win.preventNodeViewBeforeUnload = true;
});
cy.wait('@getTemplate');
cy.wait(['@createWorkflow', '@getWorkflow']);
cy.wait(['@getTemplate', '@createWorkflow', '@getWorkflow']);
},
importTemplate: (id: number, name: string, workflow: object, templatesHost: string) => {
const apiResponse = {
id,
name,
workflow,
};
cy.intercept('GET', `${templatesHost}/api/workflows/templates/${id}`, {
statusCode: 200,
body: apiResponse,
}).as('getTemplate');
importTemplate: () => {
cy.intercept('GET', 'rest/workflows/**').as('getWorkflow');
cy.visit(`/workflows/templates/${id}`);
cy.visit('/workflows/templates/1');
cy.window().then((win) => {
win.preventNodeViewBeforeUnload = true;
});
cy.wait('@getTemplate');
cy.wait('@getWorkflow');
cy.wait(['@getTemplate', '@getWorkflow']);
},
};
}

View File

@@ -283,7 +283,7 @@ export class WorkflowPage extends BasePage {
},
saveWorkflowUsingKeyboardShortcut: () => {
cy.intercept('POST', '/rest/workflows').as('createWorkflow');
cy.get('body').type(META_KEY, { release: false }).type('s');
this.actions.hitSaveWorkflow();
},
deleteNode: (name: string) => {
this.getters.canvasNodeByName(name).first().click();
@@ -339,35 +339,43 @@ export class WorkflowPage extends BasePage {
});
});
},
/** Certain keyboard shortcuts are not possible on Cypress via a simple `.type`, and some delays are needed to emulate these events */
hitComboShortcut: (modifier: string, key: string) => {
cy.get('body').wait(100).type(modifier, { delay: 100, release: false }).type(key);
},
hitUndo: () => {
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('z');
this.actions.hitComboShortcut(`{${META_KEY}}`, 'z');
},
hitRedo: () => {
cy.get('body')
.type(META_KEY, { delay: 500, release: false })
.type('{shift}', { release: false })
.type('z');
cy.get('body').type(`{${META_KEY}+shift+z}`);
},
selectAll: () => {
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('a');
hitSelectAll: () => {
this.actions.hitComboShortcut(`{${META_KEY}}`, 'a');
},
hitDeleteAllNodes: () => {
this.actions.hitSelectAll();
cy.get('body').type('{backspace}');
},
hitDisableNodeShortcut: () => {
cy.get('body').type('d');
},
hitCopy: () => {
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('c');
this.actions.hitComboShortcut(`{${META_KEY}}`, 'c');
},
hitPinNodeShortcut: () => {
cy.get('body').type('p');
},
hitExecuteWorkflowShortcut: () => {
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('{enter}');
hitSaveWorkflow: () => {
cy.get('body').type(`{${META_KEY}+s}`);
},
hitDuplicateNodeShortcut: () => {
cy.get('body').type(META_KEY, { delay: 500, release: false }).type('d');
hitExecuteWorkflow: () => {
cy.get('body').type(`{${META_KEY}+enter}`);
},
hitAddStickyShortcut: () => {
cy.get('body').type('{shift}', { delay: 500, release: false }).type('S');
hitDuplicateNode: () => {
cy.get('body').type(`{${META_KEY}+d}`);
},
hitAddSticky: () => {
cy.get('body').type('{shift+S}');
},
executeWorkflow: () => {
this.getters.executeWorkflowButton().click();