From 48adfdfcceee3aed955d9fc0017074c63a8bf9b0 Mon Sep 17 00:00:00 2001 From: Peter Sirotnak Date: Tue, 14 May 2024 10:34:44 +0200 Subject: [PATCH] PMM-12847 Grafana 10 Product tour automation (#765) * PMM-12847 Automation for product tour * PMM-12847 Correct test tag * PMM-12847 Removes skipped test * PMM-12847: Added Test numbers. * PMM-12847: Scenario .only for testing purposes * PMM-13040: Adds special tags for the pmm tour. * PMM-13040: Adds special tags for the pmm tour. * PMM-13040: changes wait for navigation * PMM-12847: Wait For Navigation fix * PMM-12847: Removes unused test flag * PMM-12847: Fix for networkidle0 * PMM-12847: Changes requested in the PR --- tests/helper/grafana_helper.js | 25 +++++++++++ .../pages/components/productTourComponent.js | 33 ++++++++++++++ tests/pages/homePage.js | 6 +++ tests/product-tour/productTour_test.js | 45 +++++++++++++++++++ tests/verifyPMMTour_test.js | 37 --------------- 5 files changed, 109 insertions(+), 37 deletions(-) create mode 100644 tests/pages/components/productTourComponent.js create mode 100644 tests/product-tour/productTour_test.js delete mode 100644 tests/verifyPMMTour_test.js diff --git a/tests/helper/grafana_helper.js b/tests/helper/grafana_helper.js index de3e51554..a221e002d 100644 --- a/tests/helper/grafana_helper.js +++ b/tests/helper/grafana_helper.js @@ -34,6 +34,31 @@ class Grafana extends Helper { Playwright.haveRequestHeaders({ Authorization: `Basic ${basicAuthEncoded}` }); } + async enableProductTour() { + const { Playwright } = this.helpers; + + await Playwright.page.route('**/v1/user', async (route, request) => { + if (request.method() === 'GET') { + await route.fulfill({ + status: 200, + body: JSON.stringify({ + user_id: 1, + product_tour_completed: false, + alerting_tour_completed: false, + }), + }); + } else { + await route.continue(); + } + }); + } + + async stopMockingProductTourApi() { + const { Playwright } = this.helpers; + + await Playwright.page.unroute('**/v1/user'); + } + async unAuthorize() { const { Playwright } = this.helpers; const { browserContext } = Playwright; diff --git a/tests/pages/components/productTourComponent.js b/tests/pages/components/productTourComponent.js new file mode 100644 index 000000000..9a77311c6 --- /dev/null +++ b/tests/pages/components/productTourComponent.js @@ -0,0 +1,33 @@ +const { I } = inject(); + +class ProductTourComponent { + constructor() { + this.productTourModal = locate('//h2[text()="Welcome to Percona Monitoring and Management (PMM)"]//ancestor::div[@role="dialog"]'); + this.skipButton = this.productTourModal.find('//span[text()="Skip"]'); + this.laterButton = this.productTourModal.find('//span[text()="Check later"]'); + this.closeButton = this.productTourModal.find('//button[@aria-label="Close"]'); + this.startTourButton = this.productTourModal.find('//span[text()="Start tour"]'); + this.nextStepButton = locate('//button[@aria-label="Next step"]'); + this.tourStepHeader = (headerText) => locate(`//div[@class="pmm-tour"]//strong[text()="${headerText}"]`); + this.productTourCategories = ['Dashboards', 'PMM Dashboards', 'PMM Query Analytics', 'Explore', 'Alerting', 'Advisors', 'Backup', 'PMM Configuration Panel', 'Administration']; + this.tourDoneButton = locate('//button//span[text()="Done"]'); + } + + async verifyProductTourSteps() { + const lastStepHeaderText = this.productTourCategories[this.productTourCategories.length - 1]; + + for (const headerText of this.productTourCategories) { + I.waitForElement(this.tourStepHeader(headerText), 10); + if (headerText === lastStepHeaderText) { + I.dontSeeElement(this.nextStepButton); + I.click(this.tourDoneButton); + } else { + I.dontSeeElement(this.tourDoneButton); + I.click(this.nextStepButton); + } + } + } +} + +module.exports = new ProductTourComponent(); +module.exports.ProductTourDialog = ProductTourComponent; diff --git a/tests/pages/homePage.js b/tests/pages/homePage.js index c7ad74c74..94ac52af1 100644 --- a/tests/pages/homePage.js +++ b/tests/pages/homePage.js @@ -1,6 +1,7 @@ const { I, dashboardPage } = inject(); const assert = require('assert'); const moment = require('moment'); +const productTourModal = require('./components/productTourComponent'); module.exports = { // insert your locators and methods here @@ -10,6 +11,9 @@ module.exports = { landingUrl: 'graph/d/pmm-home/home-dashboard?orgId=1&refresh=1m', genericOauthUrl: 'graph/login/generic_oauth', requestEnd: '/v1/Updates/Check', + elements: { + pageContent: locate('//div[@id="pageContent"]'), + }, fields: { systemsUnderMonitoringCount: locate('.panel-content span').inside('[aria-label="Monitored Nodes panel"]'), @@ -88,6 +92,8 @@ module.exports = { isAmiUpgrade: process.env.AMI_UPGRADE_TESTING_INSTANCE === 'true' || process.env.OVF_UPGRADE_TESTING_INSTANCE === 'true', pmmServerName: process.env.VM_NAME ? process.env.VM_NAME : 'pmm-server', + productTour: productTourModal, + async open() { I.amOnPage(this.url); I.waitForElement(this.fields.dashboardHeaderLocator, 60); diff --git a/tests/product-tour/productTour_test.js b/tests/product-tour/productTour_test.js new file mode 100644 index 000000000..b9ff2b51a --- /dev/null +++ b/tests/product-tour/productTour_test.js @@ -0,0 +1,45 @@ +Feature('Pmm Product tour tests'); + +Before(async ({ I }) => { + await I.stopMockingProductTourApi(); + await I.Authorize(); + await I.sendGetRequest('v1/user', { Authorization: `Basic ${await I.getAuth()}` }); +}); + +Scenario('PMM-T1879 Verify that product tour dialog is displayed after check later button pressed. @grafana-pr', async ({ I, homePage }) => { + await I.amOnPage(''); + await I.waitForElement(homePage.productTour.laterButton); + await I.click(homePage.productTour.laterButton); + await I.refreshPage(); + await I.waitForElement(homePage.productTour.productTourModal, 10); +}).config('Playwright', { waitForNavigation: 'load' }); + +Scenario('PMM-T1880 Verify that product tour dialog is displayed after closing @grafana-pr', async ({ I, homePage }) => { + await I.amOnPage(''); + await I.waitForElement(homePage.productTour.closeButton); + await I.click(homePage.productTour.closeButton); + await I.refreshPage(); + await I.waitForElement(homePage.productTour.productTourModal, 10); +}).config('Playwright', { waitForNavigation: 'load' }); + +Scenario('PMM-T1881 Verify that product tour dialog contains all the components. @grafana-pr', async ({ I, homePage }) => { + await I.amOnPage(''); + await I.waitForElement(homePage.productTour.startTourButton); + await I.click(homePage.productTour.startTourButton); + await homePage.productTour.verifyProductTourSteps(); + await I.waitForDetached(homePage.productTour.productTourModal); +}).config('Playwright', { waitForNavigation: 'load' }); + +Scenario('PMM-T1882 Verify that product tour dialog is not displayed after skipping @grafana-pr', async ({ I, homePage }) => { + await I.enableProductTour(); + await I.amOnPage(''); + + await I.waitForElement(homePage.productTour.skipButton); + await I.click(homePage.productTour.skipButton); + await I.stopMockingProductTourApi(); + + await I.refreshPage(); + + await I.waitForElement(homePage.elements.pageContent); + await I.waitForDetached(homePage.productTour.productTourModal, 10); +}).config('Playwright', { waitForNavigation: 'load' }); diff --git a/tests/verifyPMMTour_test.js b/tests/verifyPMMTour_test.js deleted file mode 100644 index 14e2dfc06..000000000 --- a/tests/verifyPMMTour_test.js +++ /dev/null @@ -1,37 +0,0 @@ -Feature('to go through new user Tour and verify it is shown once'); - -// todo: stabilize test case. Skip for now -xScenario( - 'PMM-T1272 Verify user is able to pass a PMM tour', - async ({ - I, homePage, pmmTourPage, loginPage, - }) => { - const headers = ['Dashboards', 'PMM Dashboards', 'PMM Query Analytics', 'Explore', 'Alerting', 'Advisor checks', 'Configuration Panel']; - - await I.amOnPage(loginPage.url); - loginPage.login(); - await I.executeScript(() => { - localStorage.setItem('percona.tourTest', true); - localStorage.removeItem('percona.showTour'); - }); - I.openNewTab(); - await I.amOnPage(homePage.landingUrl); - I.waitForElement(pmmTourPage.fields.startTourButton); - I.click(pmmTourPage.fields.startTourButton); - headers.forEach(((headerName) => { - I.seeElement(pmmTourPage.slideHeader(headerName)); - I.click(pmmTourPage.fields.nextSlideButton); - })); - I.seeElement(pmmTourPage.slideHeader('Server Admin')); - I.click(pmmTourPage.fields.doneButton); - - await I.unAuthorize(); - await I.amOnPage(loginPage.url); - loginPage.login(); - I.dontSee(pmmTourPage.fields.startTourButton); - await I.executeScript(() => { - localStorage.setItem('percona.tourTest', false); - localStorage.setItem('percona.showTour', false); - }); - }, -);