From f1432b26cd9b323c851e3f1eee96a835ccaf22c4 Mon Sep 17 00:00:00 2001 From: Bernat Date: Tue, 17 Mar 2020 11:00:16 +0100 Subject: [PATCH] e2e fix for linux --- e2e/helpers/extensions.js | 122 ++++++++---------- e2e/helpers/selectors.js | 8 +- .../12_lock_of_verified_data.spec.js | 4 +- e2e/paths/02-client/17_dms.spec.js | 2 +- e2e/paths/02-client/18_contacts.spec.js | 1 + e2e/paths/03-worker/04_time_control.spec.js | 9 +- ...10_item_index.spec.js => 10_index.spec.js} | 10 +- e2e/paths/05-ticket/13_services.spec.js | 2 +- e2e/paths/06-claim/04_claim_action.spec.js | 8 +- .../09-invoice-out/02_descriptor.spec.js | 4 +- e2e/paths/11-zone/01_basic-data.spec.js | 7 +- 11 files changed, 82 insertions(+), 95 deletions(-) rename e2e/paths/04-item/{10_item_index.spec.js => 10_index.spec.js} (91%) diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index 9b6a2025b..b7ef957e2 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -1,5 +1,46 @@ import {url as defaultURL} from './config'; +function checkVisibility(selector) { + let selectorMatches = document.querySelectorAll(selector); + let element = selectorMatches[0]; + + if (selectorMatches.length > 1) + throw new Error(`Multiple matches of ${selector} found`); + + let isVisible = false; + if (element) { + let eventHandler = event => { + event.preventDefault(); + isVisible = true; + }; + element.addEventListener('mouseover', eventHandler); + let rect = element.getBoundingClientRect(); + let x = rect.left + rect.width / 2; + let y = rect.top + rect.height / 2; + let elementInCenter = document.elementFromPoint(x, y); + let elementInTopLeft = document.elementFromPoint(rect.left, rect.top); + let elementInBottomRight = document.elementFromPoint(rect.right, rect.bottom); + + let e = new MouseEvent('mouseover', { + view: window, + bubbles: true, + cancelable: true, + }); + + if (elementInCenter) + elementInCenter.dispatchEvent(e); + + if (elementInTopLeft) + elementInTopLeft.dispatchEvent(e); + + if (elementInBottomRight) + elementInBottomRight.dispatchEvent(e); + + element.removeEventListener('mouseover', eventHandler); + } + return isVisible; +} + let actions = { clickIfExists: async function(selector) { let exists; @@ -99,10 +140,12 @@ let actions = { }, clearInput: async function(selector) { - await this.waitForSelector(selector, {visible: true}); + await this.waitForSelector(selector); + let field = await this.evaluate(selector => { return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field; }, selector); + if ((field != null && field != '') || field == '0') { let coords = await this.evaluate(selector => { let rect = document.querySelector(selector).getBoundingClientRect(); @@ -112,6 +155,7 @@ let actions = { await this.waitForSelector(`${selector} [icon="clear"]`, {visible: true}); await this.waitToClick(`${selector} [icon="clear"]`); } + await this.evaluate(selector => { return document.querySelector(`${selector} input`).closest('.vn-field').$ctrl.field == ''; }, selector); @@ -172,7 +216,9 @@ let actions = { waitToClick: async function(selector) { await this.waitForSelector(selector); - await this.click(selector); + await this.waitForFunction(checkVisibility, {}, selector); + + return await this.click(selector); }, writeOnEditableTD: async function(selector, text) { @@ -191,47 +237,8 @@ let actions = { }, isVisible: async function(selector) { - await this.wait(selector); - return await this.evaluate(elementSelector => { - let selectorMatches = document.querySelectorAll(elementSelector); - let element = selectorMatches[0]; - - if (selectorMatches.length > 1) - throw new Error(`Multiple matches of ${elementSelector} found`); - - let isVisible = false; - if (element) { - let eventHandler = event => { - event.preventDefault(); - isVisible = true; - }; - element.addEventListener('mouseover', eventHandler); - let rect = element.getBoundingClientRect(); - let x = rect.left + rect.width / 2; - let y = rect.top + rect.height / 2; - let elementInCenter = document.elementFromPoint(x, y); - let elementInTopLeft = document.elementFromPoint(rect.left, rect.top); - let elementInBottomRight = document.elementFromPoint(rect.right, rect.bottom); - - let e = new MouseEvent('mouseover', { - view: window, - bubbles: true, - cancelable: true, - }); - - if (elementInCenter) - elementInCenter.dispatchEvent(e); - - if (elementInTopLeft) - elementInTopLeft.dispatchEvent(e); - - if (elementInBottomRight) - elementInBottomRight.dispatchEvent(e); - - element.removeEventListener('mouseover', eventHandler); - } - return isVisible; - }, selector); + await this.waitForSelector(selector); + return await this.evaluate(checkVisibility, selector); }, waitImgLoad: async function(selector) { @@ -242,16 +249,6 @@ let actions = { }, {}, selector); }, - clickIfVisible: async function(selector) { - await this.wait(selector); - let isVisible = await this.isVisible(selector); - - if (isVisible) - return await this.click(selector); - - throw new Error(`invisible selector: ${selector}`); - }, - countElement: async function(selector) { return await this.evaluate(selector => { return document.querySelectorAll(selector).length; @@ -523,30 +520,21 @@ let actions = { waitForContentLoaded: async function() { await this.waitFor(1000); - // to be implemented in base of a directive loaded once al modules are done loading, further investigation required. - // await this.waitForFunction(() => { - // return new Promise(resolve => { - // angular.element(document).ready(() => resolve()); - // const $rootScope = angular.element(document).find('ui-view').injector().get('$rootScope'); - // $rootScope.$$postDigest(resolve()); - // $rootScope.$on('$viewContentLoaded', resolve()); - // }); - // }); }, respondToDialog: async function(response) { await this.waitForSelector('.vn-dialog.vn-popup.shown'); - const firstCount = await this.evaluate(response => { + const firstCount = await this.evaluate(text => { const dialogs = document.querySelectorAll('.vn-dialog.vn-popup'); const dialogOnTop = dialogs[dialogs.length - 1]; - const button = dialogOnTop.querySelector(`div.buttons [response="${response}"]`); + const button = dialogOnTop.querySelector(`div.buttons [response="${text}"]`); button.click(); return dialogs.length; }, response); - this.waitForFunction(count => { - let currentCount = document.querySelectorAll('.vn-dialog.vn-popup').length; - return currentCount < count; + this.waitForFunction(firstCount => { + const dialogs = document.querySelectorAll('.vn-dialog.vn-popup'); + return dialogs.length < firstCount; }, {}, firstCount); } }; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 6a742c6e3..0cee79405 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -194,8 +194,7 @@ export default { dms: { deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]', firstDocWorker: 'vn-client-dms-index vn-td:nth-child(7) > span', - firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor', - acceptDeleteButton: '.vn-confirm.shown button[response="accept"]' + firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor' }, clientContacts: { addContactButton: 'vn-client-contact vn-icon[icon="add_circle"]', @@ -207,6 +206,7 @@ export default { itemsIndex: { searchIcon: 'vn-searchbar vn-icon[icon="search"]', createItemButton: `vn-float-button`, + firstSearchResult: 'vn-item-index a:nth-child(1)', searchResult: 'vn-item-index a.vn-tr', searchResultPreviewButton: 'vn-item-index .buttons > [icon="desktop_windows"]', searchResultCloneButton: 'vn-item-index .buttons > [icon="icon-clone"]', @@ -310,7 +310,7 @@ export default { addBarcodeButton: 'vn-item-barcode vn-icon[icon="add_circle"]', thirdCode: 'vn-item-barcode vn-horizontal:nth-child(3) vn-textfield[ng-model="barcode.code"]', submitBarcodesButton: 'vn-item-barcode button[type=submit]', - firstCodeRemoveButton: 'vn-item-barcode vn-horizontal vn-none vn-icon[icon="delete"]' + firstCodeRemoveButton: 'vn-item-barcode vn-horizontal:nth-child(1) vn-icon[icon="delete"]' }, itemNiches: { addNicheButton: 'vn-item-niche vn-icon[icon="add_circle"]', @@ -536,7 +536,7 @@ export default { firstAddServiceTypeButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]', firstServiceType: 'vn-ticket-service vn-autocomplete[ng-model="service.ticketServiceTypeFk"]', firstQuantity: 'vn-ticket-service vn-input-number[ng-model="service.quantity"]', - firstPrice: 'vn-ticket-service vn-input-number[ng-model="service.price"]', + firstPrice: 'vn-ticket-service vn-horizontal:nth-child(1) vn-input-number[ng-model="service.price"]', firstVatType: 'vn-ticket-service vn-autocomplete[label="Tax class"]', fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]', newServiceTypeName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newServiceType.name"]', diff --git a/e2e/paths/02-client/12_lock_of_verified_data.spec.js b/e2e/paths/02-client/12_lock_of_verified_data.spec.js index c245860e8..870ce7cb1 100644 --- a/e2e/paths/02-client/12_lock_of_verified_data.spec.js +++ b/e2e/paths/02-client/12_lock_of_verified_data.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; -xdescribe('Client lock verified data path', () => { +describe('Client lock verified data path', () => { let browser; let page; beforeAll(async() => { @@ -113,7 +113,7 @@ xdescribe('Client lock verified data path', () => { }); }); - xdescribe('as salesAssistant', () => { + describe('as salesAssistant', () => { it('should log in as salesAssistant then get to the client fiscal data', async() => { await page.forceReloadSection('client.card.fiscalData'); await page.loginAndModule('salesAssistant', 'client'); diff --git a/e2e/paths/02-client/17_dms.spec.js b/e2e/paths/02-client/17_dms.spec.js index 9891fd3f4..95b37093a 100644 --- a/e2e/paths/02-client/17_dms.spec.js +++ b/e2e/paths/02-client/17_dms.spec.js @@ -19,7 +19,7 @@ describe('Client DMS', () => { describe('as salesPerson', () => { it('should delete de first file', async() => { await page.waitToClick(selectors.dms.deleteFileButton); - await page.waitToClick(selectors.dms.acceptDeleteButton); + await page.respondToDialog('accept'); let result = await page.waitForLastSnackbar(); expect(result).toEqual('Data saved!'); diff --git a/e2e/paths/02-client/18_contacts.spec.js b/e2e/paths/02-client/18_contacts.spec.js index 6ed8a8b82..fd8b68283 100644 --- a/e2e/paths/02-client/18_contacts.spec.js +++ b/e2e/paths/02-client/18_contacts.spec.js @@ -28,6 +28,7 @@ describe('Client contacts', () => { }); it('should delete de contact', async() => { + await page.waitFor(3000); await page.waitToClick(selectors.clientContacts.deleteFirstPhone); await page.waitToClick(selectors.clientContacts.saveButton); let result = await page.waitForLastSnackbar(); diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index 1fd23b092..ccf1ed5c3 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Worker time control path', () => { +describe('Worker time control path', () => { let browser; let page; beforeAll(async() => { @@ -313,11 +313,8 @@ fdescribe('Worker time control path', () => { it('should log in and navigate to timeControl', async() => { await page.loginAndModule('hr', 'worker'); await page.accessToSearchResult('HankPym'); - await Promise.all([ - page.waitForNavigation({waitUntil: ['load', 'networkidle0', 'domcontentloaded']}), - page.waitForContentLoaded(), - page.accessToSection('worker.card.timeControl') - ]); + await page.accessToSection('worker.card.timeControl'); + await page.waitForContentLoaded(); }); it('should lovingly scan in Hank Pym', async() => { diff --git a/e2e/paths/04-item/10_item_index.spec.js b/e2e/paths/04-item/10_index.spec.js similarity index 91% rename from e2e/paths/04-item/10_item_index.spec.js rename to e2e/paths/04-item/10_index.spec.js index 7a5491d48..e15469283 100644 --- a/e2e/paths/04-item/10_item_index.spec.js +++ b/e2e/paths/04-item/10_index.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -xdescribe('Item index path', () => { +describe('Item index path', () => { let browser; let page; beforeAll(async() => { @@ -40,7 +40,7 @@ xdescribe('Item index path', () => { }); it('should navigate forth and back to see the images column is still visible', async() => { - await page.waitToClick(selectors.itemsIndex.searchResult); + await page.waitToClick(selectors.itemsIndex.firstSearchResult); await page.waitToClick(selectors.itemDescriptor.goBackToModuleIndexButton); await page.waitToClick(selectors.itemsIndex.searchIcon); await page.wait(selectors.itemsIndex.searchResult); @@ -54,8 +54,8 @@ xdescribe('Item index path', () => { await page.waitForSelector(selectors.itemsIndex.firstItemId, {hidden: true}); }); - xit('should mark all unchecked boxes to leave the index as it was', async() => { - await page.waitForContentLoaded(); + it('should mark all unchecked boxes to leave the index as it was', async() => { + await page.waitFor(3000); // otherwise the snackbar doesnt appear some times. await page.waitToClick(selectors.itemsIndex.fieldsToShowButton); await page.waitToClick(selectors.itemsIndex.idCheckbox); await page.waitToClick(selectors.itemsIndex.stemsCheckbox); @@ -74,7 +74,7 @@ xdescribe('Item index path', () => { }); it('should now navigate forth and back to see the ids column is now visible', async() => { - await page.waitToClick(selectors.itemsIndex.searchResult); + await page.waitToClick(selectors.itemsIndex.firstSearchResult); await page.waitToClick(selectors.itemDescriptor.goBackToModuleIndexButton); await page.waitToClick(selectors.itemsIndex.searchIcon); await page.wait(selectors.itemsIndex.searchResult); diff --git a/e2e/paths/05-ticket/13_services.spec.js b/e2e/paths/05-ticket/13_services.spec.js index 0a09c7aa3..07a0a5768 100644 --- a/e2e/paths/05-ticket/13_services.spec.js +++ b/e2e/paths/05-ticket/13_services.spec.js @@ -25,7 +25,7 @@ describe('Ticket services path', () => { await page.wait(selectors.ticketService.firstAddServiceTypeButton); const result = await page.isDisabled(selectors.ticketService.firstAddServiceTypeButton); - expect(result).toBeTruthy(); + expect(result).toBe(true); }); it('should receive an error if you attempt to save a service without access rights', async() => { diff --git a/e2e/paths/06-claim/04_claim_action.spec.js b/e2e/paths/06-claim/04_claim_action.spec.js index 04c1b3f2b..1db3938d5 100644 --- a/e2e/paths/06-claim/04_claim_action.spec.js +++ b/e2e/paths/06-claim/04_claim_action.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -xdescribe('Claim action path', () => { +describe('Claim action path', () => { let browser; let page; @@ -24,8 +24,8 @@ xdescribe('Claim action path', () => { expect(result).toEqual('Data saved!'); }); - xit('should import the second importable ticket', async() => { - await page.waitFor(2000); // the animation adding the header element for the claimed total obscures somehow other elements for 2 seconds + it('should import the second importable ticket', async() => { + await page.waitFor(3000); // the animation adding the header element for the claimed total obscures somehow other elements for about 2 seconds await page.waitToClick(selectors.claimAction.importTicketButton); await page.waitToClick(selectors.claimAction.secondImportableTicket); const result = await page.waitForLastSnackbar(); @@ -63,7 +63,7 @@ xdescribe('Claim action path', () => { }); it('should check the "is paid with mana" checkbox', async() => { - page.waitFor(2500); // can't use waitForNavigation here and needs more time than a single second to get the section ready... + page.waitFor(3000); // can't use waitForNavigation here and needs more time than a single second to get the section ready... await page.waitToClick(selectors.claimAction.isPaidWithManaCheckbox); const result = await page.waitForLastSnackbar(); diff --git a/e2e/paths/09-invoice-out/02_descriptor.spec.js b/e2e/paths/09-invoice-out/02_descriptor.spec.js index d84ff78b9..e70c39ded 100644 --- a/e2e/paths/09-invoice-out/02_descriptor.spec.js +++ b/e2e/paths/09-invoice-out/02_descriptor.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -xdescribe('InvoiceOut descriptor path', () => { +describe('InvoiceOut descriptor path', () => { let browser; let page; @@ -26,7 +26,7 @@ xdescribe('InvoiceOut descriptor path', () => { expect(result).toEqual(1); }); - xit('should navigate to the invoiceOut index', async() => { + it('should navigate to the invoiceOut index', async() => { await page.waitToClick(selectors.globalItems.applicationsMenuButton); await page.wait(selectors.globalItems.applicationsMenuVisible); await page.waitToClick(selectors.globalItems.invoiceOutButton); diff --git a/e2e/paths/11-zone/01_basic-data.spec.js b/e2e/paths/11-zone/01_basic-data.spec.js index 6cd30a310..c63bb8321 100644 --- a/e2e/paths/11-zone/01_basic-data.spec.js +++ b/e2e/paths/11-zone/01_basic-data.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -xdescribe('Zone basic data path', () => { +describe('Zone basic data path', () => { let browser; let page; @@ -40,9 +40,10 @@ xdescribe('Zone basic data path', () => { await page.write(selectors.zoneBasicData.inflation, '200'); await page.waitToClick(selectors.zoneBasicData.volumetric); await page.waitToClick(selectors.zoneBasicData.saveButton); + await page.waitForContentLoaded(); }); - xit('should reload the section', async() => { + it('should now reload the section', async() => { await page.reloadSection('zone.card.basicData'); let url = await page.expectURL('#!/zone/10/basic-data'); @@ -73,7 +74,7 @@ xdescribe('Zone basic data path', () => { expect(result).toEqual('1'); }); - xit('should confirm the closing hour was updated', async() => { + it('should confirm the closing hour was updated', async() => { const result = await page.waitToGetProperty(selectors.zoneBasicData.closing, 'value'); expect(result).toEqual('21:00');