From 584212a6595bf6bdeb5022f9f4bf0ade565a3aec Mon Sep 17 00:00:00 2001 From: Carlos Jimenez Ruiz Date: Thu, 16 Jan 2020 13:40:51 +0100 Subject: [PATCH] #1976 Implementar Puppeteer autocompleteSearch fix --- e2e/helpers/extensions.js | 74 ++++++++++++++----- e2e/helpers/puppeteer.js | 4 - .../02-client-module/01_create_client.spec.js | 1 - .../02-client-module/05_add_address.spec.js | 8 +- .../12_lock_of_verified_data.spec.js | 1 - e2e/paths/02-client-module/14_balance.spec.js | 21 ++---- .../03-worker-module/02_time_control.spec.js | 7 +- e2e/paths/04-item-module/01_summary.spec.js | 2 +- .../04-item-module/02_basic_data.spec.js | 2 +- e2e/paths/04-item-module/03_tax.spec.js | 2 +- e2e/paths/04-item-module/04_tags.spec.js | 2 +- e2e/paths/04-item-module/05_niche.spec.js | 2 +- e2e/paths/04-item-module/06_botanical.spec.js | 2 +- e2e/paths/04-item-module/07_barcode.spec.js | 2 +- .../08_create_and_clone.spec.js | 2 +- .../04-item-module/09_regularize.spec.js | 12 +-- .../04-item-module/10_item_index.spec.js | 7 +- e2e/paths/04-item-module/11_item_log.spec.js | 2 +- .../04-item-module/12_descriptor.spec.js | 2 +- .../01-sale/02_edit_sale.spec.js | 4 +- .../05-ticket-module/04_packages.spec.js | 2 +- e2e/paths/06-claim-module/03_detail.spec.js | 6 +- 22 files changed, 92 insertions(+), 75 deletions(-) diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index e9f01833f..4aa5d3742 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -116,9 +116,12 @@ let actions = { return {x: rect.x + (rect.width / 2), y: rect.y + (rect.height / 2), width: rect.width}; }, selector); await this.mouse.move(coords.x, coords.y); - await this.waitFor(1000); + 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); }, getProperty: async function(selector, property) { @@ -153,8 +156,9 @@ let actions = { }, write: async function(selector, text) { - await this.wait(selector, {}); + await this.waitForSelector(selector, {}); await this.type(`${selector} input`, text); + await this.waitForTextInInput(selector, text); }, waitToClick: async function(selector) { @@ -292,7 +296,7 @@ let actions = { }, waitForURL: async function(hashURL) { - await this.wait(expectedHash => { + await this.waitForFunction(expectedHash => { return document.location.hash.includes(expectedHash); }, {}, hashURL); }, @@ -344,23 +348,34 @@ let actions = { navButton.scrollIntoViewIfNeeded(); return navButton.click(); }, sectionRoute); + await this.waitForNavigation({waitUntil: ['networkidle0']}); }, - autocompleteSearch: async function(autocompleteSelector, searchValue) { - await this.waitFor(100); // time in which the autocomplete data loads - await this.waitToClick(`${autocompleteSelector} input`); - await this.write(`.vn-drop-down.shown`, searchValue); - await this.waitFor(100); // ul to repaint - await this.waitToClick(`.vn-drop-down.shown li.active`); - await this.waitFor(200); // input to asign value - await this.wait((autocompleteSelector, searchValue) => { - return document.querySelector(`${autocompleteSelector} input`).value - .toLowerCase() - .includes(searchValue.toLowerCase()); - }, {}, autocompleteSelector, searchValue); - await this.wait(() => { - return !document.querySelector('.vn-drop-down'); - }, {}); + autocompleteSearch: async function(selector, searchValue) { + try { + await this.waitToClick(`${selector} input`), + await this.waitForSelector(selector => { + document + .querySelector(`${selector} vn-drop-down`).$ctrl.content + .querySelectorAll('li'); + }, selector); + + await this.write(`.vn-drop-down.shown`, searchValue), + await this.waitForFunction(selector => { + return document + .querySelector(`${selector} vn-drop-down`).$ctrl.content + .querySelector('li.active'); + }, {}, selector); + + await this.keyboard.press('Enter'); + await this.waitForFunction((selector, searchValue) => { + return document.querySelector(`${selector} input`).value.toLowerCase() + .includes(searchValue.toLowerCase()); + }, {}, selector, searchValue); + } catch (error) { + throw new Error(`${selector} failed to autocomplete ${searchValue}! ${error}`); + } + await this.waitForMutation(`.vn-drop-down`, 'childList'); }, reloadSection: async function(sectionRoute) { @@ -424,6 +439,29 @@ let actions = { await this.waitForSpinnerLoad(); }, + waitForMutation: async function(selector, type) { + try { + await this.evaluate((selector, type) => { + return new Promise(resolve => { + const config = {attributes: true, childList: true, subtree: true}; + const target = document.querySelector(selector); + + const onEnd = function(mutationsList, observer) { + resolve(); + + observer.disconnect(); + }; + const observer = new MutationObserver(onEnd); + observer.expectedType = type; + + observer.observe(target, config); + }); + }, selector, type); + } catch (error) { + throw new Error(`failed to wait for mutation type: ${type}`); + } + }, + waitForTransitionEnd: async function(selector) { await this.evaluate(selector => { return new Promise(resolve => { diff --git a/e2e/helpers/puppeteer.js b/e2e/helpers/puppeteer.js index cafbd7972..12787f219 100644 --- a/e2e/helpers/puppeteer.js +++ b/e2e/helpers/puppeteer.js @@ -6,10 +6,6 @@ import {url as defaultURL} from './config'; export async function getBrowser() { const browser = await Puppeteer.launch({ args: [ - // '--start-maximized' - // '--start-fullscreen' - // '--proxy-server="direct://"', - // '--proxy-bypass-list=*' `--window-size=${ 1920 },${ 1080 }`, ], defaultViewport: null, diff --git a/e2e/paths/02-client-module/01_create_client.spec.js b/e2e/paths/02-client-module/01_create_client.spec.js index a2bc5a252..95816e17e 100644 --- a/e2e/paths/02-client-module/01_create_client.spec.js +++ b/e2e/paths/02-client-module/01_create_client.spec.js @@ -57,7 +57,6 @@ describe('Client create path', async() => { await page.autocompleteSearch(selectors.createClientView.province, 'Province one'); await page.write(selectors.createClientView.city, 'Valencia'); await page.write(selectors.createClientView.postcode, '46000'); - await page.clearInput(selectors.createClientView.email); await page.write(selectors.createClientView.email, 'incorrect email format'); await page.waitToClick(selectors.createClientView.createButton); diff --git a/e2e/paths/02-client-module/05_add_address.spec.js b/e2e/paths/02-client-module/05_add_address.spec.js index 374b7c66d..67afbfdbe 100644 --- a/e2e/paths/02-client-module/05_add_address.spec.js +++ b/e2e/paths/02-client-module/05_add_address.spec.js @@ -86,11 +86,9 @@ describe('Client Add address path', () => { }); it(`should go back to the addreses section by clicking the cancel button`, async() => { - page.waitToClick(selectors.clientAddresses.cancelEditAddressButton); - await Promise.all([ - page.waitForNavigation({waitUntil: ['load', 'networkidle0', 'domcontentloaded']}), - page.waitToClick('.vn-confirm.shown button[response="accept"]') - ]); + await page.waitToClick(selectors.clientAddresses.cancelEditAddressButton); + await page.waitToClick('.vn-confirm.shown button[response="accept"]'); + await page.waitForURL('address/index'); const url = await page.parsedUrl(); expect(url.hash).toContain('address/index'); diff --git a/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js b/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js index 1a3ed3104..ddb5f6d04 100644 --- a/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js +++ b/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js @@ -128,7 +128,6 @@ describe('Client lock verified data path', () => { it('should now edit the social name', async() => { await page.clearInput(selectors.clientFiscalData.socialNameInput); - await page.waitFor(100); await page.write(selectors.clientFiscalData.socialNameInput, 'new social name edition'); await page.waitToClick(selectors.clientFiscalData.saveButton); const result = await page.waitForLastSnackbar(); diff --git a/e2e/paths/02-client-module/14_balance.spec.js b/e2e/paths/02-client-module/14_balance.spec.js index 8ac3ddb70..0acf81596 100644 --- a/e2e/paths/02-client-module/14_balance.spec.js +++ b/e2e/paths/02-client-module/14_balance.spec.js @@ -41,16 +41,18 @@ describe('Client balance path', () => { it('should click the new payment button', async() => { await page.keyboard.press('Escape'); await page.reloadSection('client.card.balance.index'); - await page.waitFor(1000); - await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.waitForURL('/balance'); + let url = await page.parsedUrl(); expect(url.hash).toContain('/balance'); }); it('should create a new payment that clears the debt', async() => { - await page.waitFor(1000); + await Promise.all([ + page.waitToClick(selectors.clientBalance.newPaymentButton), + page.waitForSelector('.vn-dialog.vn-popup.shown', {visible: true}) + ]); await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt'); await page.waitToClick(selectors.clientBalance.saveButton); let result = await page.waitForLastSnackbar(); @@ -71,16 +73,9 @@ describe('Client balance path', () => { expect(firstBalanceLine).toContain('0.00'); }); - it('should now click the new payment button', async() => { - await page.waitToClick(selectors.clientBalance.newPaymentButton); - await page.waitForURL('/balance'); - let url = await page.parsedUrl(); - - expect(url.hash).toContain('/balance'); - }); - it('should create a new payment that sets the balance to positive value', async() => { - await page.waitFor(1000); + await page.waitToClick(selectors.clientBalance.newPaymentButton); + await page.waitFor(1000); // didn't manage to make this dynamic to allow clearInput to find the icon clear... :( await page.clearInput(selectors.clientBalance.newPaymentAmountInput); await page.write(selectors.clientBalance.newPaymentAmountInput, '100'); await page.waitToClick(selectors.clientBalance.saveButton); @@ -98,7 +93,7 @@ describe('Client balance path', () => { it('should create a new payment that sets the balance back to the original negative value', async() => { await page.waitToClick(selectors.clientBalance.newPaymentButton); - await page.waitFor(1000); + await page.waitForSelector('.vn-dialog.vn-popup.shown', {visible: true}); await page.clearInput(selectors.clientBalance.newPaymentAmountInput); await page.write(selectors.clientBalance.newPaymentAmountInput, '-150'); await page.waitToClick(selectors.clientBalance.saveButton); diff --git a/e2e/paths/03-worker-module/02_time_control.spec.js b/e2e/paths/03-worker-module/02_time_control.spec.js index 343a19a15..3a0676308 100644 --- a/e2e/paths/03-worker-module/02_time_control.spec.js +++ b/e2e/paths/03-worker-module/02_time_control.spec.js @@ -389,12 +389,9 @@ describe('Worker time control path', () => { it(`should check he didn't scan in this week yet`, async() => { await page.waitToClick(selectors.workerTimeControl.navigateBackToIndex); await page.accessToSearchResult('salesBoss'); - await Promise.all([ - page.waitForNavigation({waitUntil: ['load', 'networkidle0', 'domcontentloaded']}), - page.waitForContentLoaded(), - page.accessToSection('worker.card.timeControl') - ]); + await page.accessToSection('worker.card.timeControl'); await page.waitFor(1000); + const wholeWeekHours = await page .waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText'); diff --git a/e2e/paths/04-item-module/01_summary.spec.js b/e2e/paths/04-item-module/01_summary.spec.js index 2a1b23969..f08900142 100644 --- a/e2e/paths/04-item-module/01_summary.spec.js +++ b/e2e/paths/04-item-module/01_summary.spec.js @@ -11,7 +11,7 @@ describe('Item summary path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it('should search for an item', async() => { diff --git a/e2e/paths/04-item-module/02_basic_data.spec.js b/e2e/paths/04-item-module/02_basic_data.spec.js index 88a0893bc..ec0238f09 100644 --- a/e2e/paths/04-item-module/02_basic_data.spec.js +++ b/e2e/paths/04-item-module/02_basic_data.spec.js @@ -13,7 +13,7 @@ describe('Item Edit basic data path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should check the descritor edit button is visible for buyer`, async() => { diff --git a/e2e/paths/04-item-module/03_tax.spec.js b/e2e/paths/04-item-module/03_tax.spec.js index d48bf154d..3f3b387d4 100644 --- a/e2e/paths/04-item-module/03_tax.spec.js +++ b/e2e/paths/04-item-module/03_tax.spec.js @@ -13,7 +13,7 @@ describe('Item edit tax path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should add the item tax to all countries`, async() => { diff --git a/e2e/paths/04-item-module/04_tags.spec.js b/e2e/paths/04-item-module/04_tags.spec.js index f5b849423..1665d3bab 100644 --- a/e2e/paths/04-item-module/04_tags.spec.js +++ b/e2e/paths/04-item-module/04_tags.spec.js @@ -13,7 +13,7 @@ describe('Item create tags path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should create a new tag and delete a former one`, async() => { diff --git a/e2e/paths/04-item-module/05_niche.spec.js b/e2e/paths/04-item-module/05_niche.spec.js index dd1bc013d..345b5eb8c 100644 --- a/e2e/paths/04-item-module/05_niche.spec.js +++ b/e2e/paths/04-item-module/05_niche.spec.js @@ -13,7 +13,7 @@ describe('Item create niche path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should click create a new niche and delete a former one`, async() => { diff --git a/e2e/paths/04-item-module/06_botanical.spec.js b/e2e/paths/04-item-module/06_botanical.spec.js index 8e805d17e..407dd6fc7 100644 --- a/e2e/paths/04-item-module/06_botanical.spec.js +++ b/e2e/paths/04-item-module/06_botanical.spec.js @@ -13,7 +13,7 @@ describe('Item Create botanical path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should create a new botanical for the item`, async() => { diff --git a/e2e/paths/04-item-module/07_barcode.spec.js b/e2e/paths/04-item-module/07_barcode.spec.js index fa2415fc7..dfe16f384 100644 --- a/e2e/paths/04-item-module/07_barcode.spec.js +++ b/e2e/paths/04-item-module/07_barcode.spec.js @@ -13,7 +13,7 @@ describe('Item Create barcodes path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should click create a new code and delete a former one`, async() => { diff --git a/e2e/paths/04-item-module/08_create_and_clone.spec.js b/e2e/paths/04-item-module/08_create_and_clone.spec.js index 2a50a5b94..d3601277d 100644 --- a/e2e/paths/04-item-module/08_create_and_clone.spec.js +++ b/e2e/paths/04-item-module/08_create_and_clone.spec.js @@ -11,7 +11,7 @@ describe('Item Create/Clone path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); describe('create', () => { diff --git a/e2e/paths/04-item-module/09_regularize.spec.js b/e2e/paths/04-item-module/09_regularize.spec.js index 730532d1b..4c023113c 100644 --- a/e2e/paths/04-item-module/09_regularize.spec.js +++ b/e2e/paths/04-item-module/09_regularize.spec.js @@ -11,7 +11,7 @@ describe('Item regularize path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it('should edit the user local warehouse', async() => { @@ -23,11 +23,13 @@ describe('Item regularize path', () => { expect(result).toEqual('Data saved!'); }); - it('should open the user config form to check the local settings', async() => { - await page.waitToClick(selectors.globalItems.userMenuButton); + it('should check the local settings were saved', async() => { const userLocalWarehouse = await page .waitToGetProperty(`${selectors.globalItems.userLocalWarehouse} input`, 'value'); + await page.keyboard.press('Escape'); + await page.waitForSelector('.user-popover.vn-popover', {hidden: true}); + expect(userLocalWarehouse).toContain('Warehouse Four'); }); @@ -60,7 +62,6 @@ describe('Item regularize path', () => { it('should regularize the item', async() => { await page.write(selectors.itemDescriptor.regularizeQuantityInput, '100'); - await page.wait(1000); // time for autocomplete to load await page.autocompleteSearch(selectors.itemDescriptor.regularizeWarehouseAutocomplete, 'Warehouse One'); await page.waitToClick(selectors.itemDescriptor.regularizeSaveButton); const result = await page.waitForLastSnackbar(); @@ -91,9 +92,8 @@ describe('Item regularize path', () => { it('should search for the ticket with alias missing', async() => { await page.keyboard.press('Escape'); - await page.waitForTransitionEnd('.vn-popover'); await page.write(selectors.ticketsIndex.searchTicketInput, 'missing'); - await page.waitToClick(selectors.ticketsIndex.searchButton); + await page.keyboard.press('Enter'); await page.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1); const result = await page.countElement(selectors.ticketsIndex.searchResult); diff --git a/e2e/paths/04-item-module/10_item_index.spec.js b/e2e/paths/04-item-module/10_item_index.spec.js index 7e358d96b..d09555755 100644 --- a/e2e/paths/04-item-module/10_item_index.spec.js +++ b/e2e/paths/04-item-module/10_item_index.spec.js @@ -12,7 +12,7 @@ describe('Item index path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it('should click on the fields to show button to open the list of columns to show', async() => { @@ -51,10 +51,7 @@ describe('Item index path', () => { }); it('should check the ids column is not visible', async() => { - const idVisible = await page - .isVisible(selectors.itemsIndex.firstItemId); - - expect(idVisible).toBeFalsy(); + await page.waitForSelector(selectors.itemsIndex.firstItemId, {hidden: true}); }); it('should mark all unchecked boxes to leave the index as it was', async() => { diff --git a/e2e/paths/04-item-module/11_item_log.spec.js b/e2e/paths/04-item-module/11_item_log.spec.js index d2982a59f..8c75ed0c1 100644 --- a/e2e/paths/04-item-module/11_item_log.spec.js +++ b/e2e/paths/04-item-module/11_item_log.spec.js @@ -11,7 +11,7 @@ describe('Item log path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it(`should search for the Knowledge artifact to confirm it isn't created yet`, async() => { diff --git a/e2e/paths/04-item-module/12_descriptor.spec.js b/e2e/paths/04-item-module/12_descriptor.spec.js index 7decb20c4..84614cf30 100644 --- a/e2e/paths/04-item-module/12_descriptor.spec.js +++ b/e2e/paths/04-item-module/12_descriptor.spec.js @@ -13,7 +13,7 @@ describe('Item descriptor path', () => { }); afterAll(async() => { - browser.close(); + await browser.close(); }); it('should check the descriptor inactive icon is dark as the item is active', async() => { diff --git a/e2e/paths/05-ticket-module/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket-module/01-sale/02_edit_sale.spec.js index 5a6d6cd62..f04567607 100644 --- a/e2e/paths/05-ticket-module/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket-module/01-sale/02_edit_sale.spec.js @@ -59,7 +59,6 @@ xdescribe('Ticket Edit sale path', () => { it(`should click on the zoomed image to close it`, async() => { const result = await nightmare - .wait(100) .clickIfVisible(selectors.ticketSales.firstSaleZoomedImage) .countElement(selectors.ticketSales.firstSaleZoomedImage); @@ -149,7 +148,6 @@ xdescribe('Ticket Edit sale path', () => { it('should confirm the price have been updated', async() => { const result = await nightmare - .wait(1999) .waitToGetProperty(`${selectors.ticketSales.firstSalePrice} span`, 'innerText'); expect(result).toContain('5.00'); @@ -426,7 +424,7 @@ xdescribe('Ticket Edit sale path', () => { const result = await nightmare .waitToClick(selectors.ticketSales.moreMenu) .waitToClick(selectors.ticketSales.moreMenuUpdateDiscount) - .write(selectors.ticketSales.moreMenuUpdateDiscountInput, 100) + // .write(selectors.ticketSales.moreMenuUpdateDiscountInput, 100) can't find the selector on app (deleted the selector), menu option was removed? .write('body', '\u000d') .waitForTextInElement(selectors.ticketSales.totalImport, '0.00') .waitToGetProperty(selectors.ticketSales.totalImport, 'innerText'); diff --git a/e2e/paths/05-ticket-module/04_packages.spec.js b/e2e/paths/05-ticket-module/04_packages.spec.js index b51bb8b95..1cc6a2401 100644 --- a/e2e/paths/05-ticket-module/04_packages.spec.js +++ b/e2e/paths/05-ticket-module/04_packages.spec.js @@ -54,7 +54,7 @@ describe('Ticket Create packages path', () => { it(`should confirm the first select is the expected one`, async() => { const result = await nightmare .reloadSection('ticket.card.package') - .waitForTextInInput(`${selectors.ticketPackages.firstPackageAutocomplete} input`, 'Container medical box 1m') + .waitForTextInInput(selectors.ticketPackages.firstPackageAutocomplete, 'Container medical box 1m') .waitToGetProperty(`${selectors.ticketPackages.firstPackageAutocomplete} input`, 'value'); expect(result).toEqual('7 : Container medical box 1m'); diff --git a/e2e/paths/06-claim-module/03_detail.spec.js b/e2e/paths/06-claim-module/03_detail.spec.js index 43d291bb3..eef1fa518 100644 --- a/e2e/paths/06-claim-module/03_detail.spec.js +++ b/e2e/paths/06-claim-module/03_detail.spec.js @@ -30,8 +30,8 @@ xdescribe('Claim detail', () => { it('should edit de first item claimed quantity', async() => { const result = await nightmare - .clearInput(selectors.claimDetail.firstItemQuantityInput) - .write(selectors.claimDetail.firstItemQuantityInput, 4) + .clearInput(selectors.claimDetail.firstItemQuantityInput) // selector deleted, find new upon fixes + .write(selectors.claimDetail.firstItemQuantityInput, 4) // selector deleted, find new upon fixes .write('body', '\u000d') // simulates enter .waitForLastSnackbar(); @@ -40,7 +40,7 @@ xdescribe('Claim detail', () => { it('should confirm the first item quantity, and the claimed total were correctly edited', async() => { const claimedQuantity = await nightmare - .waitToGetProperty(selectors.claimDetail.firstItemQuantityInput, 'value'); + .waitToGetProperty(selectors.claimDetail.firstItemQuantityInput, 'value'); // selector deleted, find new upon fixes const totalClaimed = await nightmare .waitToGetProperty(selectors.claimDetail.totalClaimed, 'innerText');