fix: fix 10-settings-log-streaming e2e tests

This commit is contained in:
Alex Grozav 2023-07-24 18:29:09 +03:00
parent 4b058cdcc2
commit 810567c4e8
8 changed files with 80 additions and 95 deletions

View file

@ -1,4 +1,6 @@
import { SettingsLogStreamingPage } from '../pages';
import { getVisibleModalOverlay } from '../utils/modal';
import { getVisibleDropdown } from '../utils';
const settingsLogStreamingPage = new SettingsLogStreamingPage();
@ -19,6 +21,7 @@ describe('Log Streaming Settings', () => {
});
it('should show the add destination modal', () => {
cy.enableFeature('logStreaming');
cy.visit('/settings/log-streaming');
settingsLogStreamingPage.actions.clickAddFirstDestination();
cy.wait(100);
@ -27,7 +30,7 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationButton().should('be.visible');
settingsLogStreamingPage.getters.getSelectDestinationButton().should('have.attr', 'disabled');
settingsLogStreamingPage.getters
.getDestinationModalDialog()
.getDestinationModal()
.invoke('css', 'width')
.then((widthStr) => parseInt((widthStr as unknown as string).replace('px', '')))
.should('be.lessThan', 500);
@ -36,11 +39,12 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters
.getSelectDestinationButton()
.should('not.have.attr', 'disabled');
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
getVisibleModalOverlay().click(1, 1);
settingsLogStreamingPage.getters.getDestinationModal().should('not.exist');
});
it('should create a destination and delete it', () => {
cy.enableFeature('logStreaming');
cy.visit('/settings/log-streaming');
settingsLogStreamingPage.actions.clickAddFirstDestination();
cy.wait(100);
@ -48,22 +52,26 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters.getDestinationNameInput().click()
settingsLogStreamingPage.getters.getDestinationNameInput().click();
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 0');
settingsLogStreamingPage.getters
.getDestinationNameInput()
.find('input')
.clear()
.type('Destination 0');
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
cy.wait(100);
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
getVisibleModalOverlay().click(1, 1);
cy.reload();
settingsLogStreamingPage.getters.getDestinationCards().eq(0).click();
settingsLogStreamingPage.getters.getDestinationDeleteButton().should('be.visible').click();
cy.get('.el-message-box').should('be.visible').find('.btn--cancel').click();
settingsLogStreamingPage.getters.getDestinationDeleteButton().click();
cy.get('.el-message-box').should('be.visible').find('.btn--confirm').click();
cy.reload();
});
it('should create a destination and delete it via card actions', () => {
cy.enableFeature('logStreaming');
cy.visit('/settings/log-streaming');
settingsLogStreamingPage.actions.clickAddFirstDestination();
cy.wait(100);
@ -71,30 +79,25 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters.getDestinationNameInput().click()
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 1');
settingsLogStreamingPage.getters.getDestinationNameInput().click();
settingsLogStreamingPage.getters
.getDestinationNameInput()
.find('input')
.clear()
.type('Destination 1');
settingsLogStreamingPage.getters.getDestinationSaveButton().should('not.have.attr', 'disabled');
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
cy.wait(100);
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
getVisibleModalOverlay().click(1, 1);
cy.reload();
settingsLogStreamingPage.getters
.getDestinationCards()
.eq(0)
.find('.el-dropdown-selfdefine')
.click();
cy.get('.el-dropdown-menu').find('.el-dropdown-menu__item').eq(0).click();
settingsLogStreamingPage.getters.getDestinationCards().eq(0).find('.el-dropdown').click();
getVisibleDropdown().find('.el-dropdown-menu__item').eq(0).click();
settingsLogStreamingPage.getters.getDestinationSaveButton().should('not.exist');
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
getVisibleModalOverlay().click(1, 1);
settingsLogStreamingPage.getters
.getDestinationCards()
.eq(0)
.find('.el-dropdown-selfdefine')
.click();
cy.get('.el-dropdown-menu').find('.el-dropdown-menu__item').eq(1).click();
settingsLogStreamingPage.getters.getDestinationCards().eq(0).find('.el-dropdown').click();
getVisibleDropdown().find('.el-dropdown-menu__item').eq(1).click();
cy.get('.el-message-box').should('be.visible').find('.btn--confirm').click();
cy.reload();
});
});

View file

@ -6,9 +6,11 @@ import {
} from '../constants';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
import { getVisibleDropdown, getVisibleSelect } from '../utils';
const NEW_WORKFLOW_NAME = 'Something else';
const IMPORT_WORKFLOW_URL = 'https://gist.githubusercontent.com/OlegIvaniv/010bd3f45c8a94f8eb7012e663a8b671/raw/3afea1aec15573cc168d9af7e79395bd76082906/test-workflow.json';
const IMPORT_WORKFLOW_URL =
'https://gist.githubusercontent.com/OlegIvaniv/010bd3f45c8a94f8eb7012e663a8b671/raw/3afea1aec15573cc168d9af7e79395bd76082906/test-workflow.json';
const DUPLICATE_WORKFLOW_NAME = 'Duplicated workflow';
const DUPLICATE_WORKFLOW_TAG = 'Duplicate';
@ -67,11 +69,11 @@ describe('Workflow Actions', () => {
it('should not save workflow if canvas is loading', () => {
let interceptCalledCount = 0;
// There's no way in Cypress to check if intercept was not called
// There's no way in Cypress to check if intercept was not called
// so we'll count the number of times it was called
cy.intercept('PATCH', '/rest/workflows/*', () => {
interceptCalledCount++;
}).as('saveWorkflow');
cy.intercept('PATCH', '/rest/workflows/*', () => {
interceptCalledCount++;
}).as('saveWorkflow');
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
WorkflowPage.actions.saveWorkflowOnButtonClick();
@ -84,11 +86,11 @@ describe('Workflow Actions', () => {
(req) => {
// Delay the response to give time for the save to be triggered
req.on('response', async (res) => {
await new Promise((resolve) => setTimeout(resolve, 2000))
await new Promise((resolve) => setTimeout(resolve, 2000));
res.send();
})
}
)
});
},
);
cy.reload();
cy.get('.el-loading-mask').should('exist');
cy.get('body').type(META_KEY, { release: false }).type('s');
@ -99,7 +101,7 @@ describe('Workflow Actions', () => {
cy.get('body').type(META_KEY, { release: false }).type('s');
cy.wait('@saveWorkflow');
cy.wrap(null).then(() => expect(interceptCalledCount).to.eq(1));
})
});
it('should copy nodes', () => {
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
@ -127,7 +129,7 @@ describe('Workflow Actions', () => {
cy.get('.el-message-box').should('be.visible');
cy.get('.el-message-box').find('input').type(IMPORT_WORKFLOW_URL);
cy.get('body').type('{enter}');
cy.waitForLoad(false)
cy.waitForLoad(false);
WorkflowPage.actions.zoomToFit();
WorkflowPage.getters.canvasNodes().should('have.length', 2);
WorkflowPage.getters.nodeConnections().should('have.length', 1);
@ -137,7 +139,7 @@ describe('Workflow Actions', () => {
WorkflowPage.getters
.workflowImportInput()
.selectFile('cypress/fixtures/Test_workflow-actions_paste-data.json', { force: true });
cy.waitForLoad(false)
cy.waitForLoad(false);
WorkflowPage.actions.zoomToFit();
WorkflowPage.getters.canvasNodes().should('have.length', 2);
WorkflowPage.getters.nodeConnections().should('have.length', 1);
@ -157,57 +159,33 @@ describe('Workflow Actions', () => {
WorkflowPage.getters.workflowMenuItemSettings().click();
// Change all settings
// totalWorkflows + 1 (current workflow) + 1 (no workflow option)
WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().find('li').should('have.length', totalWorkflows + 2);
WorkflowPage.getters
.workflowSettingsErrorWorkflowSelect()
WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().click();
getVisibleSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').should('exist');
WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').eq(1).click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveFiledExecutionsSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveFiledExecutionsSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveSuccessExecutionsSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveSuccessExecutionsSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveManualExecutionsSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveManualExecutionsSelect()
.find('li')
.last()
.click({ force: true });
WorkflowPage.getters
.workflowSettingsSaveExecutionProgressSelect()
.find('li')
.should('have.length', 3);
WorkflowPage.getters
.workflowSettingsSaveExecutionProgressSelect()
.find('li')
.last()
.click({ force: true });
.should('have.length', totalWorkflows + 2);
getVisibleSelect().find('li').last().click({ force: true });
WorkflowPage.getters.workflowSettingsTimezoneSelect().click();
getVisibleSelect().find('li').should('exist');
getVisibleSelect().find('li').eq(1).click({ force: true });
WorkflowPage.getters.workflowSettingsSaveFiledExecutionsSelect().click();
getVisibleSelect().find('li').should('have.length', 3);
getVisibleSelect().find('li').last().click({ force: true });
WorkflowPage.getters.workflowSettingsSaveSuccessExecutionsSelect().click();
getVisibleSelect().find('li').should('have.length', 3);
getVisibleSelect().find('li').last().click({ force: true });
WorkflowPage.getters.workflowSettingsSaveManualExecutionsSelect().click();
getVisibleSelect().find('li').should('have.length', 3);
getVisibleSelect().find('li').last().click({ force: true });
WorkflowPage.getters.workflowSettingsSaveExecutionProgressSelect().click();
getVisibleSelect().find('li').should('have.length', 3);
getVisibleSelect().find('li').last().click({ force: true });
WorkflowPage.getters.workflowSettingsTimeoutWorkflowSwitch().click();
WorkflowPage.getters.workflowSettingsTimeoutForm().find('input').first().type('1');
// Save settings
WorkflowPage.getters.workflowSettingsSaveButton().click();
WorkflowPage.getters.workflowSettingsModal().should('not.exist');
WorkflowPage.getters.successToast().should('exist');
})
});
});
it('should not be able to delete unsaved workflow', () => {

View file

@ -1,4 +1,5 @@
import { BasePage } from './base';
import { getVisibleSelect } from '../utils';
export class SettingsLogStreamingPage extends BasePage {
url = '/settings/log-streaming';
@ -6,11 +7,9 @@ export class SettingsLogStreamingPage extends BasePage {
getActionBoxUnlicensed: () => cy.getByTestId('action-box-unlicensed'),
getActionBoxLicensed: () => cy.getByTestId('action-box-licensed'),
getDestinationModal: () => cy.getByTestId('destination-modal'),
getDestinationModalDialog: () => this.getters.getDestinationModal().find('.el-dialog'),
getSelectDestinationType: () => cy.getByTestId('select-destination-type'),
getDestinationNameInput: () => cy.getByTestId('subtitle-showing-type'),
getSelectDestinationTypeItems: () =>
this.getters.getSelectDestinationType().find('.el-select-dropdown__item'),
getSelectDestinationTypeItems: () => getVisibleSelect().find('.el-select-dropdown__item'),
getSelectDestinationButton: () => cy.getByTestId('select-destination-button'),
getContactUsButton: () => this.getters.getActionBoxUnlicensed().find('button'),
getAddFirstDestinationButton: () => this.getters.getActionBoxLicensed().find('button'),

3
cypress/utils/modal.ts Normal file
View file

@ -0,0 +1,3 @@
export function getVisibleModalOverlay() {
return cy.get('.el-overlay .el-overlay-dialog').filter(':visible');
}

View file

@ -7,5 +7,5 @@ export function getVisibleSelect() {
}
export function getVisibleDropdown() {
return getVisiblePopper().filter('.el-select__dropdown');
return getVisiblePopper().filter('.el-dropdown__popper');
}

View file

@ -1,10 +1,9 @@
<template>
<span :class="$style.container" data-test-id="action-toggle">
<span @click.stop.prevent :class="$style.container" data-test-id="action-toggle">
<el-dropdown
:placement="placement"
:size="size"
trigger="click"
@click.stop
@command="onCommand"
@visible-change="onVisibleChange"
>

View file

@ -189,7 +189,7 @@ import {
defaultMessageEventBusDestinationSentryOptions,
} from 'n8n-workflow';
import type { PropType } from 'vue';
import { defineComponent } from 'vue';
import { defineComponent, nextTick } from 'vue';
import { LOG_STREAM_MODAL_KEY, MODAL_CONFIRM } from '@/constants';
import Modal from '@/components/Modal.vue';
import { useMessage } from '@/composables';
@ -375,9 +375,12 @@ export default defineComponent({
);
break;
}
if (newDestination) {
this.headerLabel = newDestination?.label ?? this.headerLabel;
this.setupNode(newDestination);
nextTick(() => {
this.setupNode(newDestination);
});
}
},
valueChanged(parameterData: IUpdateInformation) {

View file

@ -40,14 +40,14 @@ export const useLogStreamingStore = defineStore('logStreaming', {
getters: {},
actions: {
addDestination(destination: MessageEventBusDestinationOptions) {
if (destination.id && destination.id in this.items) {
if (destination.id && this.items[destination.id]) {
this.items[destination.id].destination = destination;
} else {
this.setSelectionAndBuildItems(destination);
}
},
getDestination(destinationId: string): MessageEventBusDestinationOptions | undefined {
if (destinationId in this.items) {
if (this.items[destinationId]) {
return this.items[destinationId].destination;
} else {
return;
@ -61,9 +61,9 @@ export const useLogStreamingStore = defineStore('logStreaming', {
return destinations;
},
updateDestination(destination: MessageEventBusDestinationOptions) {
if (destination.id && destination.id in this.items) {
if (destination.id && this.items[destination.id]) {
this.$patch((state) => {
if (destination.id && destination.id in this.items) {
if (destination.id && this.items[destination.id]) {
state.items[destination.id].destination = destination;
}
// to trigger refresh
@ -74,7 +74,7 @@ export const useLogStreamingStore = defineStore('logStreaming', {
removeDestination(destinationId: string) {
if (!destinationId) return;
delete this.items[destinationId];
if (destinationId in this.items) {
if (this.items[destinationId]) {
this.$patch({
items: {
...this.items,
@ -104,7 +104,7 @@ export const useLogStreamingStore = defineStore('logStreaming', {
},
getSelectedEvents(destinationId: string): string[] {
const selectedEvents: string[] = [];
if (destinationId in this.items) {
if (this.items[destinationId]) {
for (const group of this.items[destinationId].eventGroups) {
if (group.selected) {
selectedEvents.push(group.name);
@ -119,7 +119,7 @@ export const useLogStreamingStore = defineStore('logStreaming', {
return selectedEvents;
},
setSelectedInGroup(destinationId: string, name: string, isSelected: boolean) {
if (destinationId in this.items) {
if (this.items[destinationId]) {
const groupName = eventGroupFromEventName(name);
const groupIndex = this.items[destinationId].eventGroups.findIndex(
(e) => e.name === groupName,
@ -166,7 +166,7 @@ export const useLogStreamingStore = defineStore('logStreaming', {
},
setSelectionAndBuildItems(destination: MessageEventBusDestinationOptions) {
if (destination.id) {
if (!(destination.id in this.items)) {
if (!this.items[destination.id]) {
this.items[destination.id] = {
destination,
selectedEvents: new Set<string>(),