From 1a793c36e5194e694d505cf5c9fc7ec9cfd00d93 Mon Sep 17 00:00:00 2001 From: Vasyl Yurkovych <59879559+yurkovychv@users.noreply.github.com> Date: Mon, 27 Jul 2020 16:10:54 +0300 Subject: [PATCH] SAAS-263 cleanup AWS RDS skipped tests (#872) * SAAS-263 unskipped and fixed AWS RDS Mysql dedicated tests * SAAS-263 minor change * SAAS-263 adding tags * SAAS-263 fixind tests * SAAS-263 skipping QAN RDS test, fixing database checks test * SAAS-263 formatting, and fixing tests * SAAS-263 review change --- .editorconfig | 2 +- pmm-app/tests/QAN/qanPage.js | 86 +++++++++---------- pmm-app/tests/databaseChecks_test.js | 6 +- pmm-app/tests/pages/adminPage.js | 20 ++--- pmm-app/tests/pages/dashboardPage.js | 19 ++-- pmm-app/tests/pages/remoteInstancesPage.js | 12 +-- .../tests/verifyAWSRDSMySQLInstance_test.js | 60 +++++++------ 7 files changed, 103 insertions(+), 102 deletions(-) diff --git a/.editorconfig b/.editorconfig index e066097104..cf5e3c8c48 100644 --- a/.editorconfig +++ b/.editorconfig @@ -28,7 +28,7 @@ indent_style = space indent_size = 2 trim_trailing_whitespace = true -[pmm-app/tests/**.{js}] +[pmm-app/tests/**.js] indent_style = space indent_size = 2 trim_trailing_whitespace = true diff --git a/pmm-app/tests/QAN/qanPage.js b/pmm-app/tests/QAN/qanPage.js index 2865022a9c..92acd13bc9 100644 --- a/pmm-app/tests/QAN/qanPage.js +++ b/pmm-app/tests/QAN/qanPage.js @@ -1,4 +1,4 @@ -const { I, pmmSettingsPage } = inject(); +const {I, pmmSettingsPage} = inject(); const moment = require('moment'); const assert = require('assert'); module.exports = { @@ -8,6 +8,7 @@ module.exports = { 'Cluster', 'Replication Set', 'Database', + 'Schema', 'Node Name', 'Service Name', 'User Name', @@ -70,7 +71,7 @@ module.exports = { addColumnNewQAN: "//span[contains(text(), 'Add column')]", noDataIcon: 'div.ant-empty-image', querySelector: - "(//table[@class='ant-table-fixed']//tbody[@class='ant-table-tbody'])[2]//tr[4]//td[2]//div//div", + "(//table[@class='ant-table-fixed']//tbody[@class='ant-table-tbody'])[2]//tr[4]//td[2]//div//div", resizer: 'span.Resizer.horizontal', queryTime: '//tr[@data-row-key][4]//td[5]//span[1]', lockTimeDetail: "//tr[@data-row-key='lock_time']//td[4]//span[1]", @@ -90,10 +91,10 @@ module.exports = { environmentLabel: "//span[contains(text(), 'Environment')]", innodbColumn: "//tr[2]//td[6]//span[contains(@class,'summarize')]", innodbColumnTooltip: - "//tr[2]//td[6]//span[contains(@class,'ant-tooltip-open')]//span[contains(@class,'summarize')]", + "//tr[2]//td[6]//span[contains(@class,'ant-tooltip-open')]//span[contains(@class,'summarize')]", loadValue: "//td[3]//span[contains(text(),'<0.01 load')]", loadValueTooltip: - "//td[3]//span[contains(@class,'ant-tooltip-open')]//span[contains(text(),'<0.01 load')]", + "//td[3]//span[contains(@class,'ant-tooltip-open')]//span[contains(text(),'<0.01 load')]", }, metricValueLocatorOverviewTable(column, row) { @@ -126,7 +127,7 @@ module.exports = { tableHeaderLocator(tableHeader) { return ( - "//ng-select//span[contains(@class, 'ng-value-label') and contains(text(), '" + tableHeader + "')]" + "//ng-select//span[contains(@class, 'ng-value-label') and contains(text(), '" + tableHeader + "')]" ); }, @@ -134,12 +135,12 @@ module.exports = { return `(//span[@class='ant-table-header-column'])//span[contains(text(), '${columnHeader}')]`; }, - filterGroupCountSelector(groupName) { - return ( - "//section[@class='aside__filter-group']//span[contains(text(), '" + - groupName + - "')]/../button[contains(text(), 'See all')]" - ); + showAllLocator(groupName) { + return `//span[contains(text(), '${groupName}')]/../span[contains(text(), 'Show all')]` + }, + + showTop5Locator(groupName) { + return `//span[contains(text(), '${groupName}')]/../span[contains(text(), 'Show top 5')]` }, waitForFiltersLoad() { @@ -176,19 +177,14 @@ module.exports = { }, async expandAllFilter() { - for (let i = 0; i < 4; i++) { - // eslint-disable-next-line max-len - let numOfElementsFilterCount = await I.grabNumberOfVisibleElements( - this.filterGroupCountSelector(this.filterGroups[i]) + for (const i in this.filterGroups) { + const numOfElementsFilterCount = await I.grabNumberOfVisibleElements( + this.showAllLocator(this.filterGroups[i]) ); - if (numOfElementsFilterCount === 1) { - // eslint-disable-next-line max-len - I.click(this.filterGroupCountSelector(this.filterGroups[i])); - // eslint-disable-next-line max-len + if (numOfElementsFilterCount) { + I.click(this.showAllLocator(this.filterGroups[i])); I.waitForVisible( - "//section[@class='aside__filter-group']//span[contains(text(), '" + - this.filterGroups[i] + - "')]/../button[contains(text(), 'Show top 5')]" + this.showTop5Locator(this.filterGroups[i]), 30 ); } } @@ -196,21 +192,21 @@ module.exports = { async _getData(row, column) { const percentage = await I.grabTextFrom( - "//table//tr[@ng-reflect-router-link='details/," + + "//table//tr[@ng-reflect-router-link='details/," + (row - 1) + "']//app-qan-table-cell[" + column + ']//div[1]//div[3]' ); const value = await I.grabTextFrom( - "//table//tr[@ng-reflect-router-link='details/," + + "//table//tr[@ng-reflect-router-link='details/," + (row - 1) + "']//app-qan-table-cell[" + column + ']//div[1]//div[2]' ); - return { percentage: percentage, val: value }; + return {percentage: percentage, val: value}; }, async getDetailsData(row) { @@ -233,7 +229,7 @@ module.exports = { async waitForResponsePath(path) { await I.waitForResponse(request => { const url = require('url'); - const { pathname } = url.parse(request.url(), true); + const {pathname} = url.parse(request.url(), true); return path === pathname; }, 60); }, @@ -360,9 +356,9 @@ module.exports = { async checkFiltersMatchSearch(searchString) { const remainingFilters = await I.grabTextFrom('.checkbox-container__label-text'); assert.equal( - detailsQueryTimeData.percentage.indexOf(queryTimeData.percentage) > -1, - true, - "Details Query Time Percentage Doesn't Match expected " + + detailsQueryTimeData.percentage.indexOf(queryTimeData.percentage) > -1, + true, + "Details Query Time Percentage Doesn't Match expected " + detailsQueryTimeData.percentage + ' to contain ' + queryTimeData.percentage @@ -377,9 +373,9 @@ module.exports = { async checkMetricsListMatchesSearch(searchString) { const remainingMetrics = await I.grabTextFrom('.ant-select-dropdown-menu-item'); assert.equal( - detailsQueryTimeData.val.indexOf(queryTimeData.val) > -1, - true, - "Details Query Time value Doesn't Match expected " + + detailsQueryTimeData.val.indexOf(queryTimeData.val) > -1, + true, + "Details Query Time value Doesn't Match expected " + detailsQueryTimeData.val + ' to contain ' + queryTimeData.val @@ -593,7 +589,7 @@ module.exports = { async getPagesCount() { const pagesCount = - "//ul[@data-qa='qan-pagination']//li[contains(@class,'ant-pagination-item')][last()]//a"; + "//ul[@data-qa='qan-pagination']//li[contains(@class,'ant-pagination-item')][last()]//a"; const pages = await I.grabTextFrom(pagesCount); return pages; }, @@ -634,15 +630,15 @@ module.exports = { async verifyAvgQueryTime() { // eslint-disable-next-line max-len assert.equal( - await I.grabTextFrom(this.fields.overviewRowQueryCount), - await I.grabTextFrom(this.fields.qps), - 'Query Count value in Overview and Detail should match' + await I.grabTextFrom(this.fields.overviewRowQueryCount), + await I.grabTextFrom(this.fields.qps), + 'Query Count value in Overview and Detail should match' ); // eslint-disable-next-line max-len assert.equal( - await I.grabTextFrom(this.fields.overviewRowQueryTime), - await I.grabTextFrom(this.fields.queryTimeDetail), - 'Query Time value in Overview and Detail should match' + await I.grabTextFrom(this.fields.overviewRowQueryTime), + await I.grabTextFrom(this.fields.queryTimeDetail), + 'Query Time value in Overview and Detail should match' ); let [perQueryStats, perQueryUnit] = (await I.grabTextFrom(this.fields.queryTimeDetail)).split(' '); if (perQueryUnit == 'ms') { @@ -684,15 +680,15 @@ module.exports = { // eslint-disable-next-line max-len if (sortOrder === 'down') { assert.equal( - metricValue >= metricValueSecond, - true, - `Descending Sort of ${metricName} is Wrong Please check` + metricValue >= metricValueSecond, + true, + `Descending Sort of ${metricName} is Wrong Please check` ); } else { assert.equal( - metricValue <= metricValueSecond, - true, - `Ascending Sort of ${metricName} is Wrong Please check` + metricValue <= metricValueSecond, + true, + `Ascending Sort of ${metricName} is Wrong Please check` ); } } diff --git a/pmm-app/tests/databaseChecks_test.js b/pmm-app/tests/databaseChecks_test.js index db502c27ec..a966385d3b 100644 --- a/pmm-app/tests/databaseChecks_test.js +++ b/pmm-app/tests/databaseChecks_test.js @@ -29,14 +29,14 @@ Scenario( {href: `${config.url}${pmmSettingsPage.url}`}); } ); -//Skipping test because of random failings, needs investigation -xScenario( + +Scenario( 'PMM-T233 PMM-T234 Verify user is able to access PMM Database Checks through UI and with URL [critical] @not-pr-pipeline', async (I, adminPage, databaseChecksPage, pmmSettingsPage, settingsAPI) => { await settingsAPI.apiEnableSTT(); I.amOnPage(pmmSettingsPage.url); pmmSettingsPage.waitForPmmSettingsPageLoaded(); - adminPage.selectItemFromPMMDropdown('PMM Database Checks'); + await adminPage.selectItemFromPMMDropdown('PMM Database Checks'); I.waitForVisible(databaseChecksPage.fields.dbCheckPanelSelector, 30); I.amOnPage(databaseChecksPage.url); I.waitForVisible(databaseChecksPage.fields.dbCheckPanelSelector, 30); diff --git a/pmm-app/tests/pages/adminPage.js b/pmm-app/tests/pages/adminPage.js index 045e16cce9..0b103e4092 100644 --- a/pmm-app/tests/pages/adminPage.js +++ b/pmm-app/tests/pages/adminPage.js @@ -1,5 +1,5 @@ // eslint-disable-next-line no-undef -const { I } = inject(); +const {I} = inject(); const assert = require('assert'); module.exports = { @@ -15,20 +15,18 @@ module.exports = { discardChanges: '//button[@ng-click=\'ctrl.discard()\']', metricTitle: '//div[@class=\'panel-title\']', reportTitleWithNA: - '//span[contains(text(), \'N/A\')]//ancestor::div[contains(@class,\'panel-container\')]//span[contains(@class,\'panel-title-text\')]', + '//span[contains(text(), \'N/A\')]//ancestor::div[contains(@class,\'panel-container\')]//span[contains(@class,\'panel-title-text\')]', // eslint-disable-next-line no-undef pmmDropdownMenuSelector: locate('a[data-toggle="dropdown"] > span').withText('PMM') }, // introducing methods - dropdownMenuItemLocator(title) { - // eslint-disable-next-line no-undef - return locate('ul > li > a').withText(title); - }, - selectItemFromPMMDropdown(title) { + async selectItemFromPMMDropdown(title) { + title = `//li/a[text()='${title}']`; I.click(this.fields.pmmDropdownMenuSelector); - I.click(this.dropdownMenuItemLocator(title)); + I.waitForVisible(title, 30); + I.click(title); }, async navigateToDashboard(folderName, dashboardName) { @@ -112,9 +110,9 @@ module.exports = { const reportTitle = await I.grabTextFrom(this.fields.reportTitleWithNA); assert.equal( - numOfElements > number, - false, - `${numOfElements} Reports with N/A found on dashboard ${reportTitle}` + numOfElements > number, + false, + `${numOfElements} Reports with N/A found on dashboard ${reportTitle}` ); } }, diff --git a/pmm-app/tests/pages/dashboardPage.js b/pmm-app/tests/pages/dashboardPage.js index f46afd6a12..9c467c7c54 100644 --- a/pmm-app/tests/pages/dashboardPage.js +++ b/pmm-app/tests/pages/dashboardPage.js @@ -374,6 +374,10 @@ module.exports = { ], serviceName: "//label[contains(text(), 'Service Name')]/following-sibling::value-select-dropdown/descendant::a[@class='variable-value-link']", + urlWithRDSFilter: 'graph/d/mysql-instance-overview/mysql-instances-overview?orgId=1&' + + 'from=now-5m&to=now&refresh=1m&var-interval=$__auto_interval_interval&var-region=All&' + + 'var-environment=All&var-cluster=rds56-cluster&var-replication_set=All&var-az=&' + + 'var-node_type=All&var-node_model=&var-database=All&var-service_type=All&var-schema=All', }, fields: { @@ -489,16 +493,13 @@ module.exports = { I.waitForElement(this.fields.metricTitle, 30); }, - async verifyExisitngServiceName(serviceName) { - I.waitForElement(this.mySQLInstanceOverview.serviceName, 30); - I.click(this.mySQLInstanceOverview.serviceName); - const existingFilter = - "//span[@class='variable-option-icon']/following-sibling::span[contains(text(), '" + - serviceName + - "')]"; - I.seeElement(existingFilter); + expandFilters(filterType) { + const filterLocator = `//label[contains(text(), '${filterType}')]/following-sibling::value-select-dropdown`; + I.waitForElement(filterLocator, 30); + I.click(filterLocator); + return filterLocator }, - + async applyFilter(filterName, filterValue) { // eslint-disable-next-line max-len const filterSelector = `(//a[@class='variable-value-link']//ancestor::div//label[contains(text(),'${filterName}')])[1]//parent::div//a[@ng-click]`; diff --git a/pmm-app/tests/pages/remoteInstancesPage.js b/pmm-app/tests/pages/remoteInstancesPage.js index 57f05000c9..a05de6714e 100644 --- a/pmm-app/tests/pages/remoteInstancesPage.js +++ b/pmm-app/tests/pages/remoteInstancesPage.js @@ -11,12 +11,12 @@ module.exports = { // setting locators url: 'graph/d/pmm-add-instance/pmm-add-instance?orgId=1', addMySQLRemoteURL: 'graph/d/pmm-add-instance/pmm-add-instance?instance_type=mysql', - dashboardMySQLOverviewWithFilters: - 'graph/d/mysql-instance-overview/mysql-instances-overview?orgId=1&' - + 'from=now-5m&to=now&refresh=1m&var-interval=$__auto_interval_interval&var-region=us-east-1&var-environment=' - + 'RDS%20MySQL%205.6&var-cluster=rds56-cluster&var-replication_set=rds56-replication&var-node_name=rds-mysql56' - + '&var-service_name=rds-mysql56&&var-az=us-east-1c&var-node_type=remote_rds&var-node_model=&var-database=All' - + '&var-service_type=&var-schema=', + rds: { + 'Service Name': 'rds-mysql56', + 'Environment': 'RDS MySQL 5.6', + 'Replication Set': 'rds56-replication', + 'Cluster': 'rds56-cluster' + }, fields: { pageHeaderText: 'PMM Add Instance', iframe: '//div[@class=\'panel-content\']//iframe', diff --git a/pmm-app/tests/verifyAWSRDSMySQLInstance_test.js b/pmm-app/tests/verifyAWSRDSMySQLInstance_test.js index ffc5b1b1ee..e48c644107 100644 --- a/pmm-app/tests/verifyAWSRDSMySQLInstance_test.js +++ b/pmm-app/tests/verifyAWSRDSMySQLInstance_test.js @@ -6,9 +6,8 @@ Before(async (I) => { Scenario( 'PMM-T138 Verify disabling enhanced metrics for RDS, PMM-T139 Verify disabling basic metrics for RDS, PMM-T9 Verify adding RDS instances [critical] @not-pr-pipeline', - async (I, remoteInstancesPage, pmmInventoryPage, homePage, qanPage, dashboardPage) => { - const instanceIdToMonitor = 'rds-mysql56'; - const environment = 'RDS MySQL 5.6'; + async (I, remoteInstancesPage, pmmInventoryPage) => { + const instanceIdToMonitor = remoteInstancesPage.rds['Service Name']; I.amOnPage(remoteInstancesPage.url); remoteInstancesPage.waitUntilRemoteInstancesPageLoaded().openAddAWSRDSMySQLPage(); remoteInstancesPage.discoverRDS(); @@ -20,49 +19,56 @@ Scenario( pmmInventoryPage.verifyRemoteServiceIsDisplayed(instanceIdToMonitor); await pmmInventoryPage.verifyAgentHasStatusRunning(instanceIdToMonitor); await pmmInventoryPage.verifyMetricsFlags(instanceIdToMonitor); - //skipping verification of the filter in MySQL Instance Overview for now - //skipping verification of the filter in QAN. Will be fixed with new QAN tests - /* - I.amOnPage(dashboardPage.mySQLInstanceOverview.url); - await dashboardPage.verifyExisitngServiceName(instanceIdToMonitor); - I.amOnPage(qanPage.url + '?orgId=1&from=now-5m&to=now'); - await I.switchTo(qanPage.fields.iframe); - await qanPage.verifyFilterExists(environment); - */ } ); Scenario( 'Verify AWS RDS MySQL 5.6 instance has status running [critical] @pmm-post-update @not-pr-pipeline', async (I, remoteInstancesPage, pmmInventoryPage) => { - const serviceName = 'rds-mysql56'; + const serviceName = remoteInstancesPage.rds['Service Name']; I.amOnPage(pmmInventoryPage.url); pmmInventoryPage.verifyRemoteServiceIsDisplayed(serviceName); await pmmInventoryPage.verifyAgentHasStatusRunning(serviceName); } ); - +// Skipping the tests because QAN does not get any data right after instance was added for monitoring xScenario( 'Verify QAN Filters contain AWS RDS MySQL 5.6 after it was added for monitoring @not-pr-pipeline', - async (I, qanPage, adminPage) => { - const environment = 'RDS MySQL 5.6'; - const filter = qanPage.getFilterLocator(environment); + async (I, qanPage, remoteInstancesPage) => { + const filters = remoteInstancesPage.rds; I.amOnPage(qanPage.url); - await I.waitForElement(qanPage.fields.iframe, 60); - adminPage.applyTimer('5m'); - await I.switchTo(qanPage.fields.iframe); - qanPage.waitForQANPageLoaded(); + qanPage.waitForFiltersLoad(); await qanPage.expandAllFilter(); - I.seeElement(filter); + for (const filter of Object.values(filters)) { + const name = qanPage.getFilterLocator(filter); + I.waitForVisible(name, 30); + I.seeElement(name); + } } ); -xScenario( - 'Verify MySQL Instances Overview Dashboard for AWS RDS MySQL 5.6 data after it was added for monitoring', - async (I, remoteInstancesPage, dashboardPage) => { - I.amOnPage(remoteInstancesPage.dashboardMySQLOverviewWithFilters); +Scenario( + 'Verify MySQL Instances Overview Dashboard for AWS RDS MySQL 5.6 data after it was added for monitoring @not-pr-pipeline', + async (I, dashboardPage) => { + I.amOnPage(dashboardPage.mySQLInstanceOverview.urlWithRDSFilter); dashboardPage.waitForDashboardOpened(); await dashboardPage.expandEachDashboardRow(); - dashboardPage.verifyThereIsNoGraphsWithNA(); + await dashboardPage.verifyThereAreNoGraphsWithNA(); + await dashboardPage.verifyThereAreNoGraphsWithoutData(2); + } +); + +Scenario( + 'Verify MySQL Instances Overview Dashboard contains AWS RDS MySQL 5.6 filters @not-pr-pipeline', + async (I, dashboardPage, remoteInstancesPage) => { + const filters = remoteInstancesPage.rds; + I.amOnPage(dashboardPage.mySQLInstanceOverview.url); + dashboardPage.waitForDashboardOpened(); + for (const key of Object.keys(filters)) { + const locator = dashboardPage.expandFilters(key); + await within(locator, () => { + I.seeElement(locate('span').withText(filters[key])); + }); + } } );