Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PMM-12847 Grafana 10 Product tour automation #765

Merged
merged 12 commits into from
May 14, 2024
25 changes: 25 additions & 0 deletions tests/helper/grafana_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 30 additions & 0 deletions tests/pages/components/productTourComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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() {
for await (const [index, headerText] of this.productTourCategories.entries()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for await (const [index, headerText] of this.productTourCategories.entries()) {
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);
}
}
}

it adds extra verification and I believe improves readability. What do you think @peterSirotnak ?

Copy link
Contributor Author

@peterSirotnak peterSirotnak Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that is adds another level of verification but I do not think it is needed Its hardly possible to both buttons to be visible and for me it does not look more readable.

await I.waitForElement(this.tourStepHeader(headerText), 10);

if (index + 1 === this.productTourCategories.length) {
await I.click(this.tourDoneButton);
} else {
await I.click(this.nextStepButton);
}
}
}
}

module.exports = new ProductTourComponent();
module.exports.ProductTourDialog = ProductTourComponent;
6 changes: 6 additions & 0 deletions tests/pages/homePage.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -9,6 +10,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"]'),
Expand Down Expand Up @@ -86,6 +90,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);
Expand Down
45 changes: 45 additions & 0 deletions tests/product-tour/productTour_test.js
Original file line number Diff line number Diff line change
@@ -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);
});

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);
});

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);
});

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);
});
37 changes: 0 additions & 37 deletions tests/verifyPMMTour_test.js

This file was deleted.