From dc1940e8f40c1eba8ee1d68fa9f625af85d2c63f Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Tue, 8 Oct 2024 17:46:40 +0300 Subject: [PATCH 01/33] PMM-13425 remote instance tests fix --- tests/pages/remoteInstancesPage.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/pages/remoteInstancesPage.js b/tests/pages/remoteInstancesPage.js index 8b65af76d..6267c49fb 100644 --- a/tests/pages/remoteInstancesPage.js +++ b/tests/pages/remoteInstancesPage.js @@ -164,6 +164,7 @@ module.exports = { pgStatMonitorRadioInput: locate('#radio-btn-3'), customAutoDiscoveryButton: locate('//div[input[@data-testid="autoDiscoveryOptions-radio-button"]]').find('label').withText('Custom'), customAutoDiscoveryfield: '$autoDiscoveryLimit-number-input', + dropdownOption: (text) => locate('div[class$="-select-option-body"]').find('span').withText(text), }, async getFileContent(filePath) { @@ -237,8 +238,16 @@ module.exports = { return this; }, + selectDropdownOption(dropdownLocator, text) { + I.click(dropdownLocator); + I.waitForVisible(this.fields.dropdownOption(text), 30); + I.click(this.fields.dropdownOption(text)); + I.dontSeeElement(this.fields.dropdownOption(text)); + }, + async addRemoteDetails(details, skipUserNamePassword = false) { I.waitForElement(this.fields.hostName, 30); + this.selectDropdownOption('$nodes-selectbox', 'pmm-server'); I.fillField(this.fields.hostName, details.host); if (!skipUserNamePassword) { I.fillField(this.fields.userName, details.username); From 674b66fbf3992adf706d93f970b5cb41f8cbaa23 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Tue, 8 Oct 2024 18:31:06 +0300 Subject: [PATCH 02/33] PMM-13425 remote instance tests fix --- tests/pages/components/queryAnalytics/queryAnalyticsFilters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pages/components/queryAnalytics/queryAnalyticsFilters.js b/tests/pages/components/queryAnalytics/queryAnalyticsFilters.js index 06291f45c..a618a91d8 100644 --- a/tests/pages/components/queryAnalytics/queryAnalyticsFilters.js +++ b/tests/pages/components/queryAnalytics/queryAnalyticsFilters.js @@ -56,7 +56,7 @@ class QueryAnalyticsFilters { selectFilter(filterName, timeout = 30000) { I.waitForVisible(this.fields.filterBy, 30); I.usePlaywrightTo('Search and select QAN Filter', async ({ page }) => { - const locator = await page.locator(this.fields.filterByExactName(filterName).value); + const locator = page.locator(this.fields.filterByExactName(filterName).value).first(); await page.locator(this.fields.filterBy.value).fill(filterName); From 82eab542f8d56a0a23db8bbdaad8ad3d34c38dc3 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 10:24:18 +0300 Subject: [PATCH 03/33] PMM-13425 remote instance tests fix --- .../dashboards/verifyGCRemoteInstance_test.js | 2 +- tests/verifyTLSMongoDBRemoteInstance_test.js | 27 +++++---------- tests/verifyTLSMySQLRemoteInstance_test.js | 33 ++++++++----------- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/tests/dashboards/verifyGCRemoteInstance_test.js b/tests/dashboards/verifyGCRemoteInstance_test.js index 8e720130c..d449a5d78 100644 --- a/tests/dashboards/verifyGCRemoteInstance_test.js +++ b/tests/dashboards/verifyGCRemoteInstance_test.js @@ -98,7 +98,7 @@ Data(instances).Scenario( } dashboardPage.waitForDashboardOpened(); - await adminPage.applyTimeRange('Last 12 hours'); + await adminPage.applyTimeRange('Last 5 minutes'); await dashboardPage.applyFilter('Service Name', instanceDetails.serviceName); await dashboardPage.expandEachDashboardRow(); await dashboardPage.verifyThereAreNoGraphsWithoutData(1); diff --git a/tests/verifyTLSMongoDBRemoteInstance_test.js b/tests/verifyTLSMongoDBRemoteInstance_test.js index c52e53f4b..33c8b03d2 100644 --- a/tests/verifyTLSMongoDBRemoteInstance_test.js +++ b/tests/verifyTLSMongoDBRemoteInstance_test.js @@ -9,21 +9,10 @@ Feature('Monitoring SSL/TLS MongoDB instances'); const instances = new DataTable(['serviceName', 'version', 'container', 'serviceType', 'metric', 'maxQueryLength']); -instances.add(['mongodb_4.4_ssl_service', '4.4', 'mongodb_4.4', 'mongodb_ssl', 'mongodb_connections', '7']); +// instances.add(['mongodb_4.4_ssl_service', '4.4', 'mongodb_4.4', 'mongodb_ssl', 'mongodb_connections', '7']); // instances.add(['mongodb_4.2_ssl_service', '4.2', 'mongodb_4.2', 'mongodb_ssl', 'mongodb_connections']); -instances.add(['mongodb_5.0_ssl_service', '5.0', 'mongodb_5.0', 'mongodb_ssl', 'mongodb_connections', '7']); - -BeforeSuite(async ({ I, codeceptjsConfig }) => { - // await I.verifyCommand(`${pmmFrameworkLoader} --mo-version=4.2 --setup-mongodb-ssl --pmm2`); - await I.verifyCommand(`${pmmFrameworkLoader} --mo-version=4.4 --setup-mongodb-ssl --pmm2`); - await I.verifyCommand(`${pmmFrameworkLoader} --mo-version=5.0 --setup-mongodb-ssl --pmm2`); -}); - -AfterSuite(async ({ I }) => { - await I.verifyCommand('docker stop mongodb_4.4 || docker rm mongodb_4.4'); - // await I.verifyCommand('docker stop mongodb_4.2 || docker rm mongodb_4.2'); - await I.verifyCommand('docker stop mongodb_5.0 || docker rm mongodb_5.0'); -}); +// instances.add(['mongodb_5.0_ssl_service', '5.0', 'mongodb_5.0', 'mongodb_ssl', 'mongodb_connections', '7']); +instances.add(['mongodb_ssl_service', '5.0', 'psmdb-server', 'mongodb_ssl', 'mongodb_connections', '7']); Before(async ({ I, settingsAPI }) => { await I.Authorize(); @@ -149,7 +138,7 @@ Data(instances).Scenario( adminPage.performPageDown(5); await dashboardPage.expandEachDashboardRow(); adminPage.performPageUp(5); - await dashboardPage.verifyThereAreNoGraphsWithNA(); + await dashboardPage.verifyThereAreNoGraphsWithoutData(); await dashboardPage.verifyThereAreNoGraphsWithoutData(3); } }, @@ -193,14 +182,14 @@ Data(instances).Scenario( const agent_id = await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mongodb_exporter | awk -F" " '{print $4}' | awk -F"/" '{print $3}'`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm2/tmp/mongodb_exporter/agent_id/${agent_id}/ | grep caFile`); - await I.verifyCommand(`docker exec ${container} rm -r /usr/local/percona/pmm2/tmp/mongodb_exporter/`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm2/tmp/mongodb_exporter/`, 'ls: cannot access \'/usr/local/percona/pmm2/tmp/mongodb_exporter\': No such file or directory', 'fail'); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mongodb_exporter/agent_id/${agent_id}/ | grep caFile`); + await I.verifyCommand(`docker exec ${container} rm -r /usr/local/percona/pmm/tmp/mongodb_exporter/`); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mongodb_exporter/`, 'ls: cannot access \'/usr/local/percona/pmm/tmp/mongodb_exporter\': No such file or directory', 'fail'); await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mongodb_exporter | grep Running`); await I.verifyCommand(`docker exec ${container} pkill -f mongodb_exporter`); I.wait(10); await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mongodb_exporter | grep Running`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm2/tmp/mongodb_exporter/agent_id/${agent_id}/ | grep caFile`); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mongodb_exporter/agent_id/${agent_id}/ | grep caFile`); }, ).retry(1); diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 911668798..69787afc2 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -17,20 +17,15 @@ maxQueryLengthTestData.add(['^']); maxQueryLengthTestData.add(['`']); maxQueryLengthTestData.add(['"']); -instances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections']); -instances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections']); - -maxQueryLengthInstances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections', '10']); -maxQueryLengthInstances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections', '-1']); -maxQueryLengthInstances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections', '']); -maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '10']); -maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '-1']); -maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '']); - -AfterSuite(async ({ I }) => { - await I.verifyCommand('docker stop mysql_5.7 || docker rm mysql_5.7'); - await I.verifyCommand('docker stop mysql_8.0 || docker rm mysql_8.0'); -}); +// instances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections']); +instances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections']); + +// maxQueryLengthInstances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections', '10']); +// maxQueryLengthInstances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections', '-1']); +// maxQueryLengthInstances.add(['mysql_5.7_ssl_service', '5.7', 'mysql_5.7', 'mysql_ssl', 'mysql_global_status_max_used_connections', '']); +maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '10']); +maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '-1']); +maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '']); Before(async ({ I, settingsAPI }) => { await I.Authorize(); @@ -47,7 +42,6 @@ Data(instances).Scenario( let details; const remoteServiceName = `remote_${serviceName}_faker`; - await I.verifyCommand(`${pmmFrameworkLoader} --ps-version=${version} --setup-mysql-ssl --pmm2`); await I.say(await I.verifyCommand(`docker exec ${container} bash -c 'source ~/.bash_profile || true; pmm-admin list'`)); if (serviceType === 'mysql_ssl') { @@ -142,7 +136,6 @@ Data(instances).Scenario( }, ).retry(1); - Data(instances).Scenario( 'Verify dashboard after MySQL SSL Instances are added @ssl @ssl-mysql @ssl-remote @not-ui-pipeline', async ({ @@ -206,14 +199,14 @@ Data(instances).Scenario( const agent_id = await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mysqld_exporter | awk -F" " '{print $4}' | awk -F"/" '{print $3}'`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm2/tmp/mysqld_exporter/agent_id/${agent_id}/ | grep tls`); - await I.verifyCommand(`docker exec ${container} rm -r /usr/local/percona/pmm2/tmp/mysqld_exporter/`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm2/tmp/mysqld_exporter/`, 'ls: cannot access \'/usr/local/percona/pmm2/tmp/mysqld_exporter\': No such file or directory', 'fail'); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/agent_id/${agent_id}/ | grep tls`); + await I.verifyCommand(`docker exec ${container} rm -r /usr/local/percona/pmm/tmp/mysqld_exporter/`); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/`, 'ls: cannot access \'/usr/local/percona/pmm/tmp/mysqld_exporter\': No such file or directory', 'fail'); await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mysqld_exporter | grep Running`); await I.verifyCommand(`docker exec ${container} pkill -f mysqld_exporter`); I.wait(10); await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mysqld_exporter | grep Running`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm2/tmp/mysqld_exporter/agent_id/${agent_id}/ | grep tls`); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/agent_id/${agent_id}/ | grep tls`); }, ).retry(1); From d188cd9b571079ce6bc95f6aaea3b085ce897f5a Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 10:49:47 +0300 Subject: [PATCH 04/33] PMM-13425 remote instance tests fix --- .../verifyPMMServerDisconnect_test.js | 3 +- tests/pages/api/settingsAPI.js | 30 ++++--------------- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/tests/configuration/verifyPMMServerDisconnect_test.js b/tests/configuration/verifyPMMServerDisconnect_test.js index 5877c64b4..08c5af6d4 100644 --- a/tests/configuration/verifyPMMServerDisconnect_test.js +++ b/tests/configuration/verifyPMMServerDisconnect_test.js @@ -4,9 +4,10 @@ Feature('Pmm Server stability'); const pmmServerPort = '8180'; const basePmmUrl = `http://127.0.0.1:${pmmServerPort}/`; let clientServerNetwork = 'pmm-ui-tests_server-network'; +const serverImage = process.env.DOCKER_VERSION || 'perconalab/pmm-server:3-dev-latest'; BeforeSuite(async ({ I }) => { - await I.verifyCommand(`PMM_SERVER_IMAGE=${process.env.DOCKER_VERSION} docker compose -f docker-compose-disconnect.yml up -d pmm-server-disconnect`); + await I.verifyCommand(`PMM_SERVER_IMAGE=${serverImage} docker compose -f docker-compose-disconnect.yml up -d pmm-server-disconnect`); await I.asyncWaitFor(async () => await I.verifyCommand(`echo $(curl -s -o /dev/null -w '%{http_code}' 127.0.0.1:${pmmServerPort}/ping)`) === '200', 100); await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d pmm-client'); await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d mysql5.7'); diff --git a/tests/pages/api/settingsAPI.js b/tests/pages/api/settingsAPI.js index f9057d9fc..e234f006d 100644 --- a/tests/pages/api/settingsAPI.js +++ b/tests/pages/api/settingsAPI.js @@ -68,35 +68,15 @@ module.exports = { }, async apiEnableIA() { - const body = { - enable_alerting: true, - }; - const headers = { Authorization: `Basic ${await I.getAuth()}` }; - - const resp = await I.sendPostRequest(endpoint, body, headers); - - assert.ok( - resp.status === 200, - `Failed to enable Integrated alerting. ${resp.data.message}`, - ); + await this.changeSettings({ alerting: true }); }, async enableAzure() { - const body = { - enable_azurediscover: true, - }; - const headers = { Authorization: `Basic ${await I.getAuth()}` }; - - await I.sendPostRequest(endpoint, body, headers); + await this.changeSettings({ azureDiscover: true }); }, async disableAzure() { - const body = { - disable_azurediscover: true, - }; - const headers = { Authorization: `Basic ${await I.getAuth()}` }; - - await I.sendPostRequest(endpoint, body, headers); + await this.changeSettings({ azureDiscover: false }); }, async restoreSettingsDefaults() { @@ -113,7 +93,7 @@ module.exports = { }; const headers = { Authorization: `Basic ${await I.getAuth()}` }; - await I.sendPostRequest(endpoint, body, headers); + await I.sendPutRequest(endpoint, body, headers); }, async setCheckIntervals(intervals = defaultCheckIntervals) { @@ -122,7 +102,7 @@ module.exports = { }; const headers = { Authorization: `Basic ${await I.getAuth()}` }; - await I.sendPostRequest(endpoint, body, headers); + await I.sendPutRequest(endpoint, body, headers); }, async setEmailAlertingSettings(settings) { From f5570a767d85aadd2f976e1dc614c6b7ff43f97c Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 11:19:42 +0300 Subject: [PATCH 05/33] PMM-13425 ia fix --- tests/ia/pages/api/rulesAPI.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ia/pages/api/rulesAPI.js b/tests/ia/pages/api/rulesAPI.js index caa817dee..0adb9a838 100644 --- a/tests/ia/pages/api/rulesAPI.js +++ b/tests/ia/pages/api/rulesAPI.js @@ -18,7 +18,7 @@ module.exports = { { label: 'service_name', regexp: 'pmm-server-postgresql', - type: 'MATCH', + type: 'FILTER_TYPE_MATCH', }, ], for: `${(duration || 60)}s`, @@ -28,7 +28,7 @@ module.exports = { params: params || [ { name: 'threshold', - type: 'FLOAT', + type: 'PARAM_TYPE_FLOAT', float: 1, }, ], From 261fe0977bb02979d6adeca2e35d09db26482a94 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 11:57:51 +0300 Subject: [PATCH 06/33] PMM-13425 gc fix --- tests/dashboards/verifyGCRemoteInstance_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dashboards/verifyGCRemoteInstance_test.js b/tests/dashboards/verifyGCRemoteInstance_test.js index d449a5d78..3b870bc16 100644 --- a/tests/dashboards/verifyGCRemoteInstance_test.js +++ b/tests/dashboards/verifyGCRemoteInstance_test.js @@ -88,7 +88,7 @@ Data(instances).Scenario( const instanceDetails = getInstance(instance); - I.wait(10); + I.wait(30); if (instanceType === 'mysql') { I.amOnPage(dashboardPage.mySQLInstanceOverview.url); } @@ -101,7 +101,7 @@ Data(instances).Scenario( await adminPage.applyTimeRange('Last 5 minutes'); await dashboardPage.applyFilter('Service Name', instanceDetails.serviceName); await dashboardPage.expandEachDashboardRow(); - await dashboardPage.verifyThereAreNoGraphsWithoutData(1); + await dashboardPage.verifyThereAreNoGraphsWithoutData(6); }, ).retry(2); From e6d4ecfda38afb16e846367e0084f76f178c1ee1 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 12:03:07 +0300 Subject: [PATCH 07/33] PMM-13425 tls fix --- tests/pages/remoteInstancesPage.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/pages/remoteInstancesPage.js b/tests/pages/remoteInstancesPage.js index 6267c49fb..83386c759 100644 --- a/tests/pages/remoteInstancesPage.js +++ b/tests/pages/remoteInstancesPage.js @@ -274,14 +274,18 @@ module.exports = { I.dontSeeElement(this.fields.tlsCertificateInput); I.click(this.fields.useTLS); I.waitForElement(this.fields.tlscaInput, 30); + const caInput = this.fields.tlscaInput; + const certInput = this.fields.tlsCertificateInput; + const keyInput = this.fields.tlsCertificateKeyInput; + I.usePlaywrightTo('Fill TLS ca field', async ({ page }) => { - await page.fill(this.fields.tlscaInput.toXPath(), details.tlsCA); + await page.fill(caInput.toXPath(), details.tlsCA); }); I.usePlaywrightTo('Fill TLS certificate field', async ({ page }) => { - await page.fill(this.fields.tlsCertificateInput.toXPath(), details.tlsCert); + await page.fill(certInput.toXPath(), details.tlsCert); }); I.usePlaywrightTo('Fill TLS certificate key field', async ({ page }) => { - await page.fill(this.fields.tlsCertificateKeyInput.toXPath(), details.tlsKey); + await page.fill(keyInput.toXPath(), details.tlsKey); }); if (details.serviceType === 'postgres_ssl') I.click(this.fields.usePgStatStatements); From 695565a00b88ec5ce67758620c8db38683d642ca Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 12:29:00 +0300 Subject: [PATCH 08/33] PMM-13425 tls fix --- tests/pages/adminPage.js | 4 ++-- tests/pages/remoteInstancesPage.js | 18 +++++------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/tests/pages/adminPage.js b/tests/pages/adminPage.js index 0b14f0e03..e099278fc 100644 --- a/tests/pages/adminPage.js +++ b/tests/pages/adminPage.js @@ -1,12 +1,12 @@ const { I } = inject(); const assert = require('assert'); -const pathToPmmQaRepo = process.env.PATH_TO_PMM_QA || '/srv/pmm-qa'; +const pathToPmmQaRepo = process.env.PATH_TO_PMM_QA || '/srv/qa-integration'; module.exports = { url: 'graph/d/pmm-home/home-dashboard?orgId=1', pathToFramework: `${pathToPmmQaRepo}/pmm_qa/pmm-framework.py`, - pathToPMMTests: `${pathToPmmQaRepo}/pmm_qa/pmm-tests/`, + pathToPMMTests: `${pathToPmmQaRepo}/pmm_qa/`, sideMenu: { integratedAlerting: 'li > a[href="/graph/integrated-alerting"]', alertingBellIcon: locate('$navbar-section').at(2).find('li a[aria-label="Alerting"]'), diff --git a/tests/pages/remoteInstancesPage.js b/tests/pages/remoteInstancesPage.js index 83386c759..1d9e85aaf 100644 --- a/tests/pages/remoteInstancesPage.js +++ b/tests/pages/remoteInstancesPage.js @@ -274,19 +274,11 @@ module.exports = { I.dontSeeElement(this.fields.tlsCertificateInput); I.click(this.fields.useTLS); I.waitForElement(this.fields.tlscaInput, 30); - const caInput = this.fields.tlscaInput; - const certInput = this.fields.tlsCertificateInput; - const keyInput = this.fields.tlsCertificateKeyInput; - - I.usePlaywrightTo('Fill TLS ca field', async ({ page }) => { - await page.fill(caInput.toXPath(), details.tlsCA); - }); - I.usePlaywrightTo('Fill TLS certificate field', async ({ page }) => { - await page.fill(certInput.toXPath(), details.tlsCert); - }); - I.usePlaywrightTo('Fill TLS certificate key field', async ({ page }) => { - await page.fill(keyInput.toXPath(), details.tlsKey); - }); + + await this.fillFileContent(this.fields.tlscaInput, details.tlsCAFile); + await this.fillFileContent(this.fields.tlsCertificateInput, details.tlsCertFile); + await this.fillFileContent(this.fields.tlsCertificateKeyInput, details.tlsKeyFile); + if (details.serviceType === 'postgres_ssl') I.click(this.fields.usePgStatStatements); if (details.serviceType === 'mysql_ssl') I.click(this.fields.skipTLSL); From af24cb4eb429bae4d068e39cf3cb0fb08bd30c57 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 14:00:29 +0300 Subject: [PATCH 09/33] PMM-13425 update inventoryAPI.js --- tests/pages/api/inventoryAPI.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/pages/api/inventoryAPI.js b/tests/pages/api/inventoryAPI.js index 8de1857ac..3a3da36e2 100644 --- a/tests/pages/api/inventoryAPI.js +++ b/tests/pages/api/inventoryAPI.js @@ -13,8 +13,9 @@ module.exports = { // 60 sec ping for getting created service name for (let i = 0; i < 60; i++) { const resp = await this.apiGetServices(service.serviceType); + const services = Object.values(resp.data).flat(Infinity); - responseService = resp.data.services.find((service) => service.service_name === serviceName); + responseService = services.find((service) => service.service_name === serviceName); if (responseService !== undefined) break; I.wait(1); From 6a52218c1b4fee62f8cf468083ecfd739a28de13 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 17:25:33 +0300 Subject: [PATCH 10/33] PMM-13425 update inventoryAPI.js --- tests/verifyTLSMySQLRemoteInstance_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 69787afc2..04dfc5e0a 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -72,7 +72,7 @@ Data(instances).Scenario( serviceType: SERVICE_TYPE.MYSQL, service: 'mysql', }, - serviceName, + remoteServiceName, ); // Check Remote Instance also added and have running status From f4db9fac1eba7a5e27b660dac870473ebaa25592 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 20:25:50 +0300 Subject: [PATCH 11/33] PMM-13425 update inventoryAPI.js --- tests/verifyTLSMySQLRemoteInstance_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 04dfc5e0a..68cec23fb 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -270,7 +270,7 @@ Data(maxQueryLengthInstances).Scenario( serviceType: SERVICE_TYPE.MYSQL, service: 'mysql', }, - serviceName, + remoteServiceName, ); const { service_id } = await inventoryAPI.apiGetNodeInfoByServiceName(SERVICE_TYPE.MYSQL, remoteServiceName); From b24f62e92be14ff4478cebf003deaf5ab696957b Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 20:28:26 +0300 Subject: [PATCH 12/33] PMM-13425 update inventoryAPI.js --- tests/verifyTLSMySQLRemoteInstance_test.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 68cec23fb..78d02bc42 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -155,7 +155,6 @@ Data(instances).Scenario( adminPage.performPageDown(5); await dashboardPage.expandEachDashboardRow(); adminPage.performPageUp(5); - await dashboardPage.verifyThereAreNoGraphsWithNA(); await dashboardPage.verifyThereAreNoGraphsWithoutData(1); } }, @@ -175,8 +174,6 @@ Data(instances).Scenario( for (const service of serviceList) { I.amOnPage(I.buildUrlWithParams(queryAnalyticsPage.url, { from: 'now-5m' })); queryAnalyticsPage.waitForLoaded(); - await adminPage.applyTimeRange('Last 12 hours'); - queryAnalyticsPage.waitForLoaded(); await queryAnalyticsPage.filters.selectFilter(service); queryAnalyticsPage.waitForLoaded(); const count = await queryAnalyticsPage.data.getCountOfItems(); From dfcce6e385afd96c07c4be1265db8732da8d5b34 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Wed, 9 Oct 2024 21:19:08 +0300 Subject: [PATCH 13/33] PMM-13425 update inventoryAPI.js --- tests/verifyTLSMySQLRemoteInstance_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 78d02bc42..657296bbd 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -196,14 +196,14 @@ Data(instances).Scenario( const agent_id = await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mysqld_exporter | awk -F" " '{print $4}' | awk -F"/" '{print $3}'`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/agent_id/${agent_id}/ | grep tls`); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/${agent_id} | grep tls`); await I.verifyCommand(`docker exec ${container} rm -r /usr/local/percona/pmm/tmp/mysqld_exporter/`); await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/`, 'ls: cannot access \'/usr/local/percona/pmm/tmp/mysqld_exporter\': No such file or directory', 'fail'); await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mysqld_exporter | grep Running`); await I.verifyCommand(`docker exec ${container} pkill -f mysqld_exporter`); I.wait(10); await I.verifyCommand(`docker exec ${container} pmm-admin list | grep mysqld_exporter | grep Running`); - await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/agent_id/${agent_id}/ | grep tls`); + await I.verifyCommand(`docker exec ${container} ls -la /usr/local/percona/pmm/tmp/mysqld_exporter/${agent_id} | grep tls`); }, ).retry(1); From 4a08332c058a39adeb879a071266d6f17e1f8059 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 10 Oct 2024 13:06:36 +0300 Subject: [PATCH 14/33] PMM-13425 update rulesAPI.js --- tests/ia/pages/api/rulesAPI.js | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/ia/pages/api/rulesAPI.js b/tests/ia/pages/api/rulesAPI.js index 0adb9a838..a2bc78881 100644 --- a/tests/ia/pages/api/rulesAPI.js +++ b/tests/ia/pages/api/rulesAPI.js @@ -82,21 +82,9 @@ module.exports = { ); }, - async removeAllAlertRules() { - const headers = { Authorization: `Basic ${await I.getAuth()}` }; - const resp = await I.sendGetRequest('graph/api/prometheus/grafana/api/v1/rules', headers); - const allRules = resp.data.data.groups; - - if (allRules.length > 0) { - for (const i in allRules) { - await this.removeAlertRule(allRules[i].file); - } - } - }, - - async removeAlertRule(folder) { + async removeAlertRule(folderId, name) { const headers = { Authorization: `Basic ${await I.getAuth()}` }; - const resp = await I.sendDeleteRequest(`/graph/api/ruler/grafana/api/v1/rules/${folder}/default-alert-group?subtype=cortex`, headers); + const resp = await I.sendDeleteRequest(`graph/api/ruler/grafana/api/v1/rules/${folderId}/${name}?subtype=cortex`, headers); assert.ok( resp.status === 202, @@ -104,6 +92,22 @@ module.exports = { ); }, + async removeAllAlertRules() { + const headers = { Authorization: `Basic ${await I.getAuth()}` }; + const resp = await I.sendGetRequest('graph/api/ruler/grafana/api/v1/rules?subtype=cortex', headers); + const rules = Object.values(resp.data).flat(Infinity); + const allRules = rules.map((r) => { + const { name } = r; + const folderId = r.rules[0].grafana_alert.namespace_uid; + + return { name, folderId }; + }); + + for (const rule of allRules) { + await this.removeAlertRule(rule.folderId, rule.name); + } + }, + async createAlertRules(numberOfRulesToCreate) { for (let i = 0; i < numberOfRulesToCreate; i++) { await this.createAlertRule({ ruleName: `${faker.lorem.word()}_alert_rule` }); From 86706b528d032ccb99fcbb3178e621167a04f4ab Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 10 Oct 2024 14:24:07 +0300 Subject: [PATCH 15/33] PMM-13425 ia tests --- tests/ia/alertRules_test.js | 12 ++-- tests/ia/alerts_test.js | 4 +- tests/ia/common_test.js | 4 +- tests/ia/contactPoints_test.js | 100 ++++++++++++++++----------------- tests/ia/pagination_test.js | 6 +- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/tests/ia/alertRules_test.js b/tests/ia/alertRules_test.js index 2334a0cd4..0153df94a 100644 --- a/tests/ia/alertRules_test.js +++ b/tests/ia/alertRules_test.js @@ -27,7 +27,7 @@ After(async () => { await rulesAPI.removeAllAlertRules(); }); -Scenario.skip( +Scenario( 'PMM-T1384 Verify empty alert rules list @ia @grafana-pr', async ({ I, alertRulesPage }) => { alertRulesPage.openAlertRulesTab(); @@ -40,7 +40,7 @@ Scenario.skip( }, ).retry(0); -Scenario.skip( +Scenario( 'PMM-T1385 Verify alert rules elements @ia @grafana-pr', async ({ I, alertRulesPage, rulesAPI }) => { const ruleName = 'testRule'; @@ -71,7 +71,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T1392 Verify fields dynamically change value when template is changed @ia @grafana-pr', async ({ I, alertRulesPage }) => { // TODO: https://jira.percona.com/browse/PMM-10860 name doesn't change @@ -88,7 +88,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T1420 Verify user can create Percona templated alert @ia @alerting-fb', async ({ I, alertRulesPage, rulesAPI }) => { const rule = page.rules[15]; @@ -137,7 +137,7 @@ Scenario.skip( ); // TODO: check ovf failure -Scenario.skip( +Scenario( 'PMM-T1430 Verify user can edit Percona templated alert @ia @not-ovf @alerting-fb', async ({ I, alertRulesPage, rulesAPI, @@ -163,7 +163,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T1433 Verify user can delete Percona templated alert @ia @alerting-fb', async ({ I, alertRulesPage, rulesAPI, iaCommon, diff --git a/tests/ia/alerts_test.js b/tests/ia/alerts_test.js index 35d6d3d6a..937d6ac51 100644 --- a/tests/ia/alerts_test.js +++ b/tests/ia/alerts_test.js @@ -33,12 +33,12 @@ BeforeSuite(async ({ I, rulesAPI }) => { await rulesAPI.createAlertRule({ ruleName }, ruleFolder); // Preparation steps for checking Alert via webhook server - await I.verifyCommand('docker-compose -f docker-compose-webhook.yml up -d'); + await I.verifyCommand('docker compose -f docker-compose-webhook.yml up -d'); }); AfterSuite(async ({ rulesAPI, I }) => { await rulesAPI.removeAllAlertRules(); - await I.verifyCommand('docker-compose -f docker-compose-webhook.yml stop'); + await I.verifyCommand('docker compose -f docker-compose-webhook.yml stop'); }); Scenario.skip( diff --git a/tests/ia/common_test.js b/tests/ia/common_test.js index 76c12db9b..f755a11d9 100644 --- a/tests/ia/common_test.js +++ b/tests/ia/common_test.js @@ -7,7 +7,7 @@ Before(async ({ I, rulesAPI }) => { await rulesAPI.removeAllAlertRules(); }); -Scenario.skip( +Scenario( 'PMM-T643 Verify message about disabled IA @ia @alerting-fb', async ({ I, pmmSettingsPage, codeceptjsConfig, @@ -23,7 +23,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T481 Verify IA tab bar, ' + 'PMM-T620 Verify after reloading the page user is on the same IA tab, ' + 'PMM-T776 Verify that user is able to see valid HTML Title on alerts page @ia @alerting-fb', diff --git a/tests/ia/contactPoints_test.js b/tests/ia/contactPoints_test.js index d74bff8d7..60aa99809 100644 --- a/tests/ia/contactPoints_test.js +++ b/tests/ia/contactPoints_test.js @@ -12,58 +12,58 @@ Before(async ({ I }) => { await I.Authorize(); }); -// Data(contactPoints).Scenario( -// 'PMM-T1703 Verify Slack contact point can be created, ' -// + 'PMM-T1709 Verify Webhook contact point can be created @ia', -// async ({ I, current }) => { -// await contactPointsPage.openContactPointsTab(); -// await contactPointsPage.createCP(current.name, current.type); -// I.click(contactPointsPage.buttons.saveCP); -// I.verifyPopUpMessage(contactPointsPage.messages.cPCreatedSuccess); -// await contactPointsPage.verifyCPInTable(current.name); -// }, -// ); -// -// Data(contactPoints).Scenario( -// 'PMM-T1707 Verify Slack contact point can be edited @ia', -// async ({ I, current }) => { -// await contactPointsPage.openContactPointsTab(); -// await contactPointsPage.editCP(current.name); -// I.appendField(contactPointsPage.fields.cPName, editedCPName); -// I.click(contactPointsPage.buttons.saveCP); -// I.verifyPopUpMessage(contactPointsPage.messages.cPEditedSuccess); -// await contactPointsPage.verifyCPInTable(current.name + editedCPName); -// }, -// ); -// -// Scenario.skip( -// 'PMM-T1706 Verify default contact point cannot be deleted @ia', -// async ({ I }) => { -// await contactPointsPage.openContactPointsTab(); -// await contactPointsPage.deleteCP('default'); -// I.waitForVisible(contactPointsPage.elements.cannotdeleteCPDialogHeader, 10); -// I.see(contactPointsPage.messages.cPCannotDelete); -// I.click(contactPointsPage.buttons.closeModal); -// I.see('default', contactPointsPage.elements.cPTable); -// }, -// ); -// -// Data(contactPoints).Scenario( -// 'PMM-T1704 Verify Slack contact point can be deleted @ia', -// async ({ I, current }) => { -// const name = current.name + editedCPName; -// -// await contactPointsPage.openContactPointsTab(); -// await contactPointsPage.deleteCP(name); -// I.waitForVisible(contactPointsPage.elements.deleteCPDialogHeader, 10); -// I.see(contactPointsPage.messages.deleteCPConfirm(name)); -// I.click(contactPointsPage.buttons.confirmDeleteCP); -// I.verifyPopUpMessage(contactPointsPage.messages.cPDeletedSuccess); -// I.dontSee(name, contactPointsPage.elements.cPTable); -// }, -// ); +Data(contactPoints).Scenario( + 'PMM-T1703 Verify Slack contact point can be created, ' + + 'PMM-T1709 Verify Webhook contact point can be created @ia', + async ({ I, current }) => { + await contactPointsPage.openContactPointsTab(); + await contactPointsPage.createCP(current.name, current.type); + I.click(contactPointsPage.buttons.saveCP); + I.verifyPopUpMessage(contactPointsPage.messages.cPCreatedSuccess); + await contactPointsPage.verifyCPInTable(current.name); + }, +); + +Data(contactPoints).Scenario( + 'PMM-T1707 Verify Slack contact point can be edited @ia', + async ({ I, current }) => { + await contactPointsPage.openContactPointsTab(); + await contactPointsPage.editCP(current.name); + I.appendField(contactPointsPage.fields.cPName, editedCPName); + I.click(contactPointsPage.buttons.saveCP); + I.verifyPopUpMessage(contactPointsPage.messages.cPEditedSuccess); + await contactPointsPage.verifyCPInTable(current.name + editedCPName); + }, +); Scenario.skip( + 'PMM-T1706 Verify default contact point cannot be deleted @ia', + async ({ I }) => { + await contactPointsPage.openContactPointsTab(); + await contactPointsPage.deleteCP('default'); + I.waitForVisible(contactPointsPage.elements.cannotdeleteCPDialogHeader, 10); + I.see(contactPointsPage.messages.cPCannotDelete); + I.click(contactPointsPage.buttons.closeModal); + I.see('default', contactPointsPage.elements.cPTable); + }, +); + +Data(contactPoints).Scenario( + 'PMM-T1704 Verify Slack contact point can be deleted @ia', + async ({ I, current }) => { + const name = current.name + editedCPName; + + await contactPointsPage.openContactPointsTab(); + await contactPointsPage.deleteCP(name); + I.waitForVisible(contactPointsPage.elements.deleteCPDialogHeader, 10); + I.see(contactPointsPage.messages.deleteCPConfirm(name)); + I.click(contactPointsPage.buttons.confirmDeleteCP); + I.verifyPopUpMessage(contactPointsPage.messages.cPDeletedSuccess); + I.dontSee(name, contactPointsPage.elements.cPTable); + }, +); + +Scenario( 'PMM-T1710 Verify saving a contact point when required info is missing, ' + 'PMM-T1711 Verify contact point test @ia', async ({ I, iaCommon }) => { diff --git a/tests/ia/pagination_test.js b/tests/ia/pagination_test.js index 51ca49fc7..aea1920b1 100644 --- a/tests/ia/pagination_test.js +++ b/tests/ia/pagination_test.js @@ -12,7 +12,7 @@ After(async ({ templatesAPI }) => { await templatesAPI.clearAllTemplates(); }); -Scenario.skip( +Scenario( 'PMM-T632 PMM-T697 PMM-T701 PMM-T1251 Verify Pagination navigation @ia @grafana-pr', async ({ I, iaCommon, @@ -143,7 +143,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T662 PMM-T698 PMM-T702 PMM-T631 PMM-T1251 Pagination rows per page persistence @ia', async ({ I, iaCommon, @@ -218,7 +218,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T631 PMM-T633 PMM-T1251 Changing rows per page resets view to 1 page @ia', async ({ I, iaCommon, templatesAPI, From b5aa9c1651ed440d9c8f47b4a0d2b33f79aa5b84 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 10 Oct 2024 14:50:40 +0300 Subject: [PATCH 16/33] PMM-13425 tls mongo tests --- tests/verifyTLSMongoDBRemoteInstance_test.js | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/verifyTLSMongoDBRemoteInstance_test.js b/tests/verifyTLSMongoDBRemoteInstance_test.js index 33c8b03d2..d7241b4f8 100644 --- a/tests/verifyTLSMongoDBRemoteInstance_test.js +++ b/tests/verifyTLSMongoDBRemoteInstance_test.js @@ -12,7 +12,7 @@ const instances = new DataTable(['serviceName', 'version', 'container', 'service // instances.add(['mongodb_4.4_ssl_service', '4.4', 'mongodb_4.4', 'mongodb_ssl', 'mongodb_connections', '7']); // instances.add(['mongodb_4.2_ssl_service', '4.2', 'mongodb_4.2', 'mongodb_ssl', 'mongodb_connections']); // instances.add(['mongodb_5.0_ssl_service', '5.0', 'mongodb_5.0', 'mongodb_ssl', 'mongodb_connections', '7']); -instances.add(['mongodb_ssl_service', '5.0', 'psmdb-server', 'mongodb_ssl', 'mongodb_connections', '7']); +instances.add(['mongodb_ssl_service', '6.0', 'psmdb-server', 'mongodb_ssl', 'mongodb_connections', '7']); Before(async ({ I, settingsAPI }) => { await I.Authorize(); @@ -37,9 +37,9 @@ Data(instances).Scenario( host: container, cluster: 'mongodb_remote_cluster', environment: 'mongodb_remote_cluster', - tlsCAFile: `${pathToPMMFramework}tls-ssl-setup/mongodb/${version}/ca.crt`, - tlsCertificateFilePasswordInput: `${pathToPMMFramework}tls-ssl-setup/mongodb/${version}/client.key`, - tlsCertificateKeyFile: `${pathToPMMFramework}tls-ssl-setup/mongodb/${version}/client.pem`, + tlsCAFile: `${pathToPMMFramework}../pmm_psmdb_diffauth_setup/certs/ca-certs.pem`, + tlsCertificateFilePasswordInput: `${pathToPMMFramework}../pmm_psmdb_diffauth_setup/certs/certificate.crt`, + tlsCertificateKeyFile: `${pathToPMMFramework}../pmm_psmdb_diffauth_setup/certs/client.pem`, }; } @@ -53,7 +53,7 @@ Data(instances).Scenario( serviceType: SERVICE_TYPE.MONGODB, service: 'mongodb', }, - serviceName, + remoteServiceName, ); // Check Remote Instance also added and have running status @@ -79,10 +79,10 @@ Data(instances).Scenario( I.wait(10); // verify metric for client container node instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: serviceName }); + response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); result = JSON.stringify(response.data.data.result); - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${serviceName} should be available but got empty ${result}`); + assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); // verify metric for remote instance response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); @@ -212,9 +212,9 @@ Data(instances).Scenario( host: container, cluster: 'mongodb_remote_cluster', environment: 'mongodb_remote_cluster', - tlsCAFile: `${pathToPMMFramework}tls-ssl-setup/mongodb/${version}/ca.crt`, - tlsCertificateFilePasswordInput: `${pathToPMMFramework}tls-ssl-setup/mongodb/${version}/client.key`, - tlsCertificateKeyFile: `${pathToPMMFramework}tls-ssl-setup/mongodb/${version}/client.pem`, + tlsCAFile: `${pathToPMMFramework}../pmm_psmdb_diffauth_setup/certs/ca-certs.pem`, + tlsCertificateFilePasswordInput: `${pathToPMMFramework}../pmm_psmdb_diffauth_setup/certs/certificate.crt`, + tlsCertificateKeyFile: `${pathToPMMFramework}../pmm_psmdb_diffauth_setup/certs/client.pem`, }; } @@ -232,7 +232,7 @@ Data(instances).Scenario( serviceType: SERVICE_TYPE.MONGODB, service: 'mongodb', }, - serviceName, + remoteServiceName, ); const { service_id } = await inventoryAPI.apiGetNodeInfoByServiceName(SERVICE_TYPE.MONGODB, remoteServiceName); From 275af10e75c22f2f53be326f56a37c66dfd7ffa0 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 10 Oct 2024 17:28:18 +0300 Subject: [PATCH 17/33] PMM-13425 fix checkMetric method --- tests/ia/ruleTemplates_test.js | 22 ++++++------ tests/pages/api/grafanaAPI.js | 65 +++++++++++++++++----------------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/tests/ia/ruleTemplates_test.js b/tests/ia/ruleTemplates_test.js index b9950f4bf..91c41fadd 100644 --- a/tests/ia/ruleTemplates_test.js +++ b/tests/ia/ruleTemplates_test.js @@ -154,7 +154,7 @@ Scenario.skip( // }, // ); -Scenario.skip( +Scenario( '@PMM-T1785 Bulk rule templates upload @ia', async ({ I, ruleTemplatesPage }) => { const path = 'tests/ia/templates/multiple-templates.yml'; @@ -179,7 +179,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( '@PMM-T1786 Edit bulk uploaded rule template @ia', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = 'tests/ia/templates/multiple-templates.yml'; @@ -216,7 +216,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( '@PMM-T1787 Delete bulk uploaded rule template @ia', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = 'tests/ia/templates/multiple-templates.yml'; @@ -248,7 +248,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T501 Upload duplicate rule template @ia @grafana-pr', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; @@ -266,7 +266,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T483 PMM-T699 Verify user can edit UI-created IA rule template @ia @grafana-pr @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; @@ -297,7 +297,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T562 Verify user can delete User-defined (UI) rule templates @ia @grafana-pr @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; @@ -326,7 +326,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T884 Verify templates from Percona (SAAS) cannot be deleted or edited @ia', async ({ I, ruleTemplatesPage }) => { const saasDeleteButton = ruleTemplatesPage.buttons @@ -341,7 +341,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T553 Verify rule template can be deleted if there is a rule based on it @ia', async ({ I, ruleTemplatesPage, templatesAPI, rulesAPI, @@ -363,7 +363,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T825 PMM-T821 Verify User can add Alert rule template in the file system @not-ovf @ia', async ({ I, ruleTemplatesPage }) => { const editButton = ruleTemplatesPage.buttons @@ -385,7 +385,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'PMM-T1126 - Verify there are no Templates from Percona if Telemetry is disabled @ia', async ({ I, settingsAPI, ruleTemplatesPage }) => { const editButton = ruleTemplatesPage.buttons @@ -405,7 +405,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( '@PMM-T1514 Verify that alert rule templates has only 1 exit button @ia', async ({ I, ruleTemplatesPage, alertRulesPage }) => { ruleTemplatesPage.openRuleTemplatesTab(); diff --git a/tests/pages/api/grafanaAPI.js b/tests/pages/api/grafanaAPI.js index 40faa1b3f..2ef75cf30 100644 --- a/tests/pages/api/grafanaAPI.js +++ b/tests/pages/api/grafanaAPI.js @@ -206,10 +206,12 @@ module.exports = { const headers = { Authorization: `Basic ${await I.getAuth()}` }; const resp = await I.sendGetRequest(`graph/api/dashboards/uid/${uid}`, headers); + assert.ok( - resp.status === 200, - `Failed to find dashboard with id '${uid}' . Response message is ${resp.data.message}`, + resp.status === 200, + `Failed to find dashboard with id '${uid}' . Response message is ${resp.data.message}`, ); + return resp.data; }, @@ -342,45 +344,41 @@ module.exports = { ); }, - // Should be refactored - async getMetric(metricName, refineBy) { - const timeStamp = Date.now(); - const bodyFormData = new FormData(); - - const body = { - query: metricName, - start: Math.floor((timeStamp - 15000) / 1000), - end: Math.floor((timeStamp) / 1000), - step: 1, + async getDataSourceUidByName(name = 'Metrics') { + const headers = { + Authorization: `Basic ${await I.getAuth()}`, }; - if (refineBy) { - // ideally would need to refactor existing metric check to implement it this way - if (Array.isArray(refineBy)) { - let metricLabels = ''; - - for (let i = 0; i < refineBy.length; i++) { - const { type, value } = refineBy[i]; - const filter = `${type}="${value}", `; + const r = await I.sendGetRequest( + 'graph/api/datasources', + headers, + ); - metricLabels = metricLabels.concat(filter); - } + return (r.data.find((d) => d.name === name)).uid; + }, - body.query = `${metricName}{${metricLabels}}`; - } else { - body.query = `${metricName}{${refineBy.type}=~"(${refineBy.value})"}`; - } - } + // Should be refactored + async getMetric(metricName, refineBy) { + const uid = await this.getDataSourceUidByName(); + const body = { + queries: [ + { + datasource: { + uid, + }, + expr: `${metricName}{${refineBy.type}=\"${refineBy.value}\"}`, + }, + ], + from: 'now-15m', + }; - Object.keys(body).forEach((key) => bodyFormData.append(key, body[key])); const headers = { Authorization: `Basic ${await I.getAuth()}`, - ...bodyFormData.getHeaders(), }; return await I.sendPostRequest( - 'graph/api/datasources/proxy/1/api/v1/query_range', - bodyFormData, + 'graph/api/ds/query?ds_type=prometheus&requestId=explore_vmt', + body, headers, ); }, @@ -459,10 +457,11 @@ module.exports = { async checkMetricExist(metricName, refineBy) { const response = await this.getMetric(metricName, refineBy); - const result = JSON.stringify(response.data.data.result); + + const result = JSON.stringify(response.data.results); I.assertTrue( - response.data.data.result.length !== 0, + response.data.results.A.frames[0].data.values.length !== 0, `Metrics '${metricName}' ${refineBy === null ? '' : `with filters as ${JSON.stringify(refineBy)} `}should be available but got empty ${result}`, ); From ed61208bb17d713858a601f832894ebfc67523c7 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 10 Oct 2024 17:44:48 +0300 Subject: [PATCH 18/33] PMM-13425 fix tls mysql --- tests/verifyTLSMySQLRemoteInstance_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 657296bbd..cc4a954b0 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -96,10 +96,10 @@ Data(instances).Scenario( I.wait(10); // verify metric for client container node instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: serviceName }); + response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); result = JSON.stringify(response.data.data.result); - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${serviceName} should be available but got empty ${result}`); + assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); // verify metric for remote instance response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); From c80da790ad5d944367ddc9844132d34ca29e95e4 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 10 Oct 2024 18:04:28 +0300 Subject: [PATCH 19/33] PMM-13425 fix tls mysql --- tests/verifyTLSMySQLRemoteInstance_test.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index cc4a954b0..9371d8ef1 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -89,23 +89,15 @@ Data(instances).Scenario( const { serviceName, metric, } = current; - let response; let result; const remoteServiceName = `remote_${serviceName}_faker`; // Waiting for metrics to start hitting for remotely added services I.wait(10); // verify metric for client container node instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); - result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); - + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); // verify metric for remote instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); - result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); }, ).retry(1); From 074c22d7f2d9fc8c2cf1afadc15853540049425e Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 11 Oct 2024 11:54:54 +0300 Subject: [PATCH 20/33] PMM-13425 fix tls mysql --- tests/verifyTLSMySQLRemoteInstance_test.js | 31 ++++++++++------------ 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 9371d8ef1..595eff937 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -27,8 +27,13 @@ maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'm maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '-1']); maxQueryLengthInstances.add(['mysql_8.0_ssl_service', '8.0', 'mysql_ssl_8.0', 'mysql_ssl', 'mysql_global_status_max_used_connections', '']); -Before(async ({ I, settingsAPI }) => { +let serviceName; + +Before(async ({ I, inventoryAPI }) => { await I.Authorize(); + const { service_name } = await inventoryAPI.apiGetNodeInfoByServiceName(SERVICE_TYPE.MYSQL, 'mysql_8.0_ssl_service'); + + serviceName = service_name; }); Data(instances).Scenario( @@ -37,7 +42,7 @@ Data(instances).Scenario( I, remoteInstancesPage, pmmInventoryPage, current, inventoryAPI, }) => { const { - serviceName, serviceType, version, container, + serviceType, version, container, } = current; let details; const remoteServiceName = `remote_${serviceName}_faker`; @@ -87,7 +92,7 @@ Data(instances).Scenario( I, remoteInstancesPage, pmmInventoryPage, current, grafanaAPI, }) => { const { - serviceName, metric, + metric, } = current; const remoteServiceName = `remote_${serviceName}_faker`; @@ -95,7 +100,7 @@ Data(instances).Scenario( I.wait(10); // verify metric for client container node instance - await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: serviceName }); // verify metric for remote instance await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); }, @@ -128,15 +133,11 @@ Data(instances).Scenario( }, ).retry(1); -Data(instances).Scenario( +Scenario( 'Verify dashboard after MySQL SSL Instances are added @ssl @ssl-mysql @ssl-remote @not-ui-pipeline', async ({ - I, dashboardPage, adminPage, current, + I, dashboardPage, adminPage, }) => { - const { - serviceName, - } = current; - const serviceList = [serviceName, `remote_${serviceName}`]; for (const service of serviceList) { @@ -152,15 +153,11 @@ Data(instances).Scenario( }, ).retry(2); -Data(instances).Scenario( +Scenario( 'Verify QAN after MySQL SSL Instances is added @ssl @ssl-mysql @ssl-remote @not-ui-pipeline', async ({ - I, queryAnalyticsPage, current, adminPage, + I, queryAnalyticsPage, }) => { - const { - serviceName, - } = current; - const serviceList = [serviceName, `remote_${serviceName}_faker`]; for (const service of serviceList) { @@ -223,7 +220,7 @@ Data(maxQueryLengthInstances).Scenario( I, remoteInstancesPage, pmmInventoryPage, inventoryAPI, current, queryAnalyticsPage, }) => { const { - serviceName, serviceType, version, container, maxQueryLength, + serviceType, version, container, maxQueryLength, } = current; let details; const remoteServiceName = `MaxQueryLength_remote_${serviceName}_${faker.random.alphaNumeric(3)}`; From 69f10fb3366208258f371a71f38b80c99c69456c Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 11 Oct 2024 12:09:28 +0300 Subject: [PATCH 21/33] PMM-13425 fix tls mysql --- tests/pages/api/inventoryAPI.js | 1 - tests/verifyTLSMySQLRemoteInstance_test.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/pages/api/inventoryAPI.js b/tests/pages/api/inventoryAPI.js index 3a3da36e2..91f40a09f 100644 --- a/tests/pages/api/inventoryAPI.js +++ b/tests/pages/api/inventoryAPI.js @@ -52,7 +52,6 @@ module.exports = { const resp = await this.apiGetServices(serviceType); const data = Object.values(resp.data).flat() - .filter((entry) => entry) .filter(({ service_name }) => service_name.includes(serviceName)); if (data.length === 0) await I.say(`Service "${serviceName}" of "${serviceType}" type is not found!`); diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 595eff937..692019276 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -31,7 +31,7 @@ let serviceName; Before(async ({ I, inventoryAPI }) => { await I.Authorize(); - const { service_name } = await inventoryAPI.apiGetNodeInfoByServiceName(SERVICE_TYPE.MYSQL, 'mysql_8.0_ssl_service'); + const { service_name } = await inventoryAPI.apiGetNodeInfoByServiceName(SERVICE_TYPE.MYSQL, 'mysql_ssl_8.0_ssl_service'); serviceName = service_name; }); From 4ddd73d86f57dc7a068abe1e75b7606d3b9b6a55 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 11 Oct 2024 12:48:42 +0300 Subject: [PATCH 22/33] PMM-13425 fix tls mysql --- tests/verifyTLSMySQLRemoteInstance_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/verifyTLSMySQLRemoteInstance_test.js b/tests/verifyTLSMySQLRemoteInstance_test.js index 692019276..1bf3a07ce 100644 --- a/tests/verifyTLSMySQLRemoteInstance_test.js +++ b/tests/verifyTLSMySQLRemoteInstance_test.js @@ -97,7 +97,7 @@ Data(instances).Scenario( const remoteServiceName = `remote_${serviceName}_faker`; // Waiting for metrics to start hitting for remotely added services - I.wait(10); + I.wait(60); // verify metric for client container node instance await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: serviceName }); From 819abc659b6cc4f75c9dfb0aca3326396626f0ba Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 11 Oct 2024 13:16:43 +0300 Subject: [PATCH 23/33] PMM-13425 fix ia --- tests/ia/pages/api/templatesAPI.js | 2 +- tests/ia/ruleTemplates_test.js | 130 ++++++++++++++--------------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/tests/ia/pages/api/templatesAPI.js b/tests/ia/pages/api/templatesAPI.js index 1ffca8301..78b25ee49 100644 --- a/tests/ia/pages/api/templatesAPI.js +++ b/tests/ia/pages/api/templatesAPI.js @@ -31,7 +31,7 @@ module.exports = { } for (const { source, name } of templates) { - if (source === 'USER_API') { await this.removeTemplate(name); } + if (source === 'TEMPLATE_SOURCE_USER_API') { await this.removeTemplate(name); } } }, diff --git a/tests/ia/ruleTemplates_test.js b/tests/ia/ruleTemplates_test.js index 91c41fadd..efe0027f9 100644 --- a/tests/ia/ruleTemplates_test.js +++ b/tests/ia/ruleTemplates_test.js @@ -52,7 +52,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'Verify rule templates list elements @ia @grafana-pr', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; @@ -78,7 +78,7 @@ Scenario.skip( }, ); -Scenario.skip( +Scenario( 'Add rule template modal elements @ia @grafana-pr', async ({ I, ruleTemplatesPage }) => { ruleTemplatesPage.openRuleTemplatesTab(); @@ -92,69 +92,69 @@ Scenario.skip( ); // nightly candidate -// Data(units).Scenario( -// 'PMM-T500 PMM-T595 PMM-T596 Add rule templates with different units, empty range @ia', -// async ({ -// I, ruleTemplatesPage, templatesAPI, current, -// }) => { -// const [templateName, fileContent, id] = await ruleTemplatesPage.ruleTemplate -// .templateNameAndContent(ruleTemplatesPage.ruleTemplate.inputFilePath); -// const editButton = ruleTemplatesPage.buttons -// .editButtonByName(templateName); -// const deleteButton = ruleTemplatesPage.buttons -// .deleteButtonByName(templateName); -// -// const newFileContent = fileContent -// .replace('unit: \'%\'', `unit: '${current.unit}'`) -// .replace('range: [0, 100]', `range: ${current.range}`); -// -// ruleTemplatesPage.openRuleTemplatesTab(); -// -// I.click(ruleTemplatesPage.buttons.openAddTemplateModal); -// I.fillField(ruleTemplatesPage.fields.templateInput, newFileContent); -// I.click(ruleTemplatesPage.buttons.addTemplate); -// if (current.unit !== '*') { -// I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); -// -// // Check that Edit and Delete buttons are enabled -// I.waitForEnabled(editButton); -// I.waitForEnabled(deleteButton); -// -// await templatesAPI.removeTemplate(id); -// } else { -// I.verifyPopUpMessage(ruleTemplatesPage.messages.failedToParse); -// } -// }, -// ); - -// Data(templates).Scenario( -// 'PMM-T482 PMM-T499 PMM-T766 PMM-T758 PMM-T766 PMM-T767 PMM-T931 Upload rule templates @ia', -// async ({ I, ruleTemplatesPage, current }) => { -// const { path } = current; -// const validFile = !current.error; -// const [templateName] = await ruleTemplatesPage.ruleTemplate.templateNameAndContent(path); -// const expectedSourceLocator = ruleTemplatesPage -// .getSourceLocator(templateName, ruleTemplatesPage.templateSources.ui); -// const editButton = ruleTemplatesPage.buttons -// .editButtonBySource(ruleTemplatesPage.templateSources.ui); -// -// ruleTemplatesPage.openRuleTemplatesTab(); -// I.click(ruleTemplatesPage.buttons.openAddTemplateModal); -// I.attachFile(ruleTemplatesPage.fields.fileInput, path); -// await ruleTemplatesPage.verifyInputContent(path); -// I.click(ruleTemplatesPage.buttons.addTemplate); -// -// if (validFile) { -// I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); -// I.waitForVisible(expectedSourceLocator, 30); -// I.waitForEnabled(editButton); -// } else { -// I.verifyPopUpMessage(current.error); -// } -// }, -// ); +Data(units).Scenario( + 'PMM-T500 PMM-T595 PMM-T596 Add rule templates with different units, empty range @ia', + async ({ + I, ruleTemplatesPage, templatesAPI, current, + }) => { + const [templateName, fileContent, id] = await ruleTemplatesPage.ruleTemplate + .templateNameAndContent(ruleTemplatesPage.ruleTemplate.inputFilePath); + const editButton = ruleTemplatesPage.buttons + .editButtonByName(templateName); + const deleteButton = ruleTemplatesPage.buttons + .deleteButtonByName(templateName); -Scenario( + const newFileContent = fileContent + .replace('unit: \'%\'', `unit: '${current.unit}'`) + .replace('range: [0, 100]', `range: ${current.range}`); + + ruleTemplatesPage.openRuleTemplatesTab(); + + I.click(ruleTemplatesPage.buttons.openAddTemplateModal); + I.fillField(ruleTemplatesPage.fields.templateInput, newFileContent); + I.click(ruleTemplatesPage.buttons.addTemplate); + if (current.unit !== '*') { + I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); + + // Check that Edit and Delete buttons are enabled + I.waitForEnabled(editButton); + I.waitForEnabled(deleteButton); + + await templatesAPI.removeTemplate(id); + } else { + I.verifyPopUpMessage(ruleTemplatesPage.messages.failedToParse); + } + }, +); + +Data(templates).Scenario( + 'PMM-T482 PMM-T499 PMM-T766 PMM-T758 PMM-T766 PMM-T767 PMM-T931 Upload rule templates @ia', + async ({ I, ruleTemplatesPage, current }) => { + const { path } = current; + const validFile = !current.error; + const [templateName] = await ruleTemplatesPage.ruleTemplate.templateNameAndContent(path); + const expectedSourceLocator = ruleTemplatesPage + .getSourceLocator(templateName, ruleTemplatesPage.templateSources.ui); + const editButton = ruleTemplatesPage.buttons + .editButtonBySource(ruleTemplatesPage.templateSources.ui); + + ruleTemplatesPage.openRuleTemplatesTab(); + I.click(ruleTemplatesPage.buttons.openAddTemplateModal); + I.attachFile(ruleTemplatesPage.fields.fileInput, path); + await ruleTemplatesPage.verifyInputContent(path); + I.click(ruleTemplatesPage.buttons.addTemplate); + + if (validFile) { + I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); + I.waitForVisible(expectedSourceLocator, 30); + I.waitForEnabled(editButton); + } else { + I.verifyPopUpMessage(current.error); + } + }, +); + +Scenario.only( '@PMM-T1785 Bulk rule templates upload @ia', async ({ I, ruleTemplatesPage }) => { const path = 'tests/ia/templates/multiple-templates.yml'; @@ -174,7 +174,7 @@ Scenario( .editButtonBySource(ruleTemplatesPage.templateSources.ui); I.waitForVisible(expectedSourceLocator, 30); - I.seeElementsEnabled(editButton); + I.seeElement(editButton); } }, ); From e32d21bc222de97a08f36d55a6549a6ab05163b2 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 11 Oct 2024 13:32:54 +0300 Subject: [PATCH 24/33] PMM-13425 fix ia --- tests/ia/ruleTemplates_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ia/ruleTemplates_test.js b/tests/ia/ruleTemplates_test.js index efe0027f9..e1b94ec5c 100644 --- a/tests/ia/ruleTemplates_test.js +++ b/tests/ia/ruleTemplates_test.js @@ -154,7 +154,7 @@ Data(templates).Scenario( }, ); -Scenario.only( +Scenario( '@PMM-T1785 Bulk rule templates upload @ia', async ({ I, ruleTemplatesPage }) => { const path = 'tests/ia/templates/multiple-templates.yml'; From 8975277a0d16cafd72690387d6c5604b4ddf1cb7 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 11 Oct 2024 13:37:27 +0300 Subject: [PATCH 25/33] PMM-13425 fix metrics checks --- .../dashboards/verifyGCRemoteInstance_test.js | 7 ++----- tests/verifyRemoteInstances_test.js | 5 +---- tests/verifyTLSMongoDBRemoteInstance_test.js | 19 +++++++++---------- tests/verifyTLSPostgresRemoteInstance_test.js | 14 ++------------ 4 files changed, 14 insertions(+), 31 deletions(-) diff --git a/tests/dashboards/verifyGCRemoteInstance_test.js b/tests/dashboards/verifyGCRemoteInstance_test.js index 3b870bc16..95bedf4a9 100644 --- a/tests/dashboards/verifyGCRemoteInstance_test.js +++ b/tests/dashboards/verifyGCRemoteInstance_test.js @@ -136,11 +136,8 @@ Data(instances).Scenario( const instanceDetails = getInstance(instance); - I.wait(10); - const response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: instanceDetails.serviceName }); - const result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${instanceDetails.serviceName} should be available but got empty ${result}`); + I.wait(30); + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: instanceDetails.serviceName }); }, ); diff --git a/tests/verifyRemoteInstances_test.js b/tests/verifyRemoteInstances_test.js index ab0ce038e..5414a44b0 100644 --- a/tests/verifyRemoteInstances_test.js +++ b/tests/verifyRemoteInstances_test.js @@ -340,9 +340,6 @@ Scenario( pmmInventoryPage.verifyRemoteServiceIsDisplayed(remoteServiceName); await pmmInventoryPage.verifyAgentHasStatusRunning(remoteServiceName); // verify metric for client container node instance - const response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); - const result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); }, ); diff --git a/tests/verifyTLSMongoDBRemoteInstance_test.js b/tests/verifyTLSMongoDBRemoteInstance_test.js index d7241b4f8..8c0b57c39 100644 --- a/tests/verifyTLSMongoDBRemoteInstance_test.js +++ b/tests/verifyTLSMongoDBRemoteInstance_test.js @@ -14,8 +14,14 @@ const instances = new DataTable(['serviceName', 'version', 'container', 'service // instances.add(['mongodb_5.0_ssl_service', '5.0', 'mongodb_5.0', 'mongodb_ssl', 'mongodb_connections', '7']); instances.add(['mongodb_ssl_service', '6.0', 'psmdb-server', 'mongodb_ssl', 'mongodb_connections', '7']); -Before(async ({ I, settingsAPI }) => { +let serviceName; + +Before(async ({ I, inventoryAPI }) => { await I.Authorize(); + + const { service_name } = await inventoryAPI.apiGetNodeInfoByServiceName(SERVICE_TYPE.MONGODB, 'mongodb_ssl_service'); + + serviceName = service_name; }); Data(instances).Scenario( @@ -79,16 +85,9 @@ Data(instances).Scenario( I.wait(10); // verify metric for client container node instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); - result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); - + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: serviceName }); // verify metric for remote instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); - result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); }, ).retry(1); diff --git a/tests/verifyTLSPostgresRemoteInstance_test.js b/tests/verifyTLSPostgresRemoteInstance_test.js index 36d321bc5..96c9cb3fc 100644 --- a/tests/verifyTLSPostgresRemoteInstance_test.js +++ b/tests/verifyTLSPostgresRemoteInstance_test.js @@ -88,8 +88,6 @@ Data(instances).Scenario( const { serviceName, metric, container, } = current; - let response; - let result; const remoteServiceName = `remote_${serviceName}`; // Waiting for metrics to start hitting for remotely added services @@ -98,17 +96,9 @@ Data(instances).Scenario( // verify metric for client container node instance const localServiceName = await I.verifyCommand(`docker exec ${container} pmm-admin list | grep "PostgreSQL" | grep "ssl_service" | awk -F " " '{print $2}'`); - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: localServiceName }); - - result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${serviceName} should be available but got empty ${result}`); - + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: localServiceName }); // verify metric for remote instance - response = await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); - result = JSON.stringify(response.data.data.result); - - assert.ok(response.data.data.result.length !== 0, `Metrics ${metric} from ${remoteServiceName} should be available but got empty ${result}`); + await grafanaAPI.checkMetricExist(metric, { type: 'service_name', value: remoteServiceName }); }, ).retry(1); From 8e6357dc7721b9c000d8f61e1c636dba227eeb7f Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Mon, 14 Oct 2024 13:00:32 +0300 Subject: [PATCH 26/33] PMM-13425 ia fixes --- tests/ia/alertRules_test.js | 5 +++-- tests/ia/contactPoints_test.js | 10 ++++------ tests/ia/pages/alertRulesPage.js | 18 +++++++++++++----- tests/ia/pages/api/rulesAPI.js | 8 ++++---- tests/ia/pages/contactPointsPage.js | 12 +++++++++--- tests/ia/pages/ruleTemplatesPage.js | 2 ++ tests/ia/ruleTemplates_test.js | 20 +++++++------------- 7 files changed, 42 insertions(+), 33 deletions(-) diff --git a/tests/ia/alertRules_test.js b/tests/ia/alertRules_test.js index 0153df94a..488b17219 100644 --- a/tests/ia/alertRules_test.js +++ b/tests/ia/alertRules_test.js @@ -21,6 +21,7 @@ Feature('Alerting: Alert rules'); Before(async ({ I }) => { await I.Authorize(); + await rulesAPI.removeAllAlertRules(); }); After(async () => { @@ -78,10 +79,10 @@ Scenario( alertRulesPage.openAlertRulesTab(); I.click(alertRulesPage.buttons.newAlertRule); I.waitForElement(alertRulesPage.fields.templatesLoader); - alertRulesPage.searchAndSelectResult('template', 'PostgreSQL down'); + await alertRulesPage.searchAndSelectResult('template', 'PostgreSQL down'); I.waitForValue(alertRulesPage.fields.inputField('duration'), '60s'); I.seeTextEquals('Critical', alertRulesPage.fields.dropdownValue('severity')); - alertRulesPage.searchAndSelectResult('template', 'MySQL restarted'); + await alertRulesPage.searchAndSelectResult('template', 'MySQL restarted'); I.waitForValue(alertRulesPage.fields.inputField('threshold'), 300); I.waitForValue(alertRulesPage.fields.inputField('duration'), '60s'); I.seeTextEquals('Warning', alertRulesPage.fields.dropdownValue('severity')); diff --git a/tests/ia/contactPoints_test.js b/tests/ia/contactPoints_test.js index 60aa99809..527b9ded0 100644 --- a/tests/ia/contactPoints_test.js +++ b/tests/ia/contactPoints_test.js @@ -36,15 +36,13 @@ Data(contactPoints).Scenario( }, ); -Scenario.skip( +Scenario( 'PMM-T1706 Verify default contact point cannot be deleted @ia', async ({ I }) => { await contactPointsPage.openContactPointsTab(); - await contactPointsPage.deleteCP('default'); - I.waitForVisible(contactPointsPage.elements.cannotdeleteCPDialogHeader, 10); - I.see(contactPointsPage.messages.cPCannotDelete); - I.click(contactPointsPage.buttons.closeModal); - I.see('default', contactPointsPage.elements.cPTable); + await contactPointsPage.openMoreMenu('default'); + I.waitForVisible(contactPointsPage.buttons.deleteCP, 10); + I.seeAttributesOnElements(contactPointsPage.buttons.deleteCP, { disabled: 'true' }); }, ); diff --git a/tests/ia/pages/alertRulesPage.js b/tests/ia/pages/alertRulesPage.js index 4d44d6d56..bdb9395ca 100644 --- a/tests/ia/pages/alertRulesPage.js +++ b/tests/ia/pages/alertRulesPage.js @@ -29,29 +29,34 @@ module.exports = { }, buttons: { newAlertRule: '//a[contains(.,\'New alert rule\')]', - saveAndExit: locate('button').withText('Save and exit'), + saveAndExit: locate('button').withText('Save rule and exit'), editAlertRule: '//a[contains(@href, \'edit?returnTo=%2Falerting%2Flist\')]', editRuleOnView: '//span[text()="Edit"]', deleteAlertRule: locate('span').withText('Delete').inside('button'), - groupCollapseButton: (folderText) => `//button[@data-testid='group-collapse-toggle'][following::h6[contains(., '${folderText}')]]`, + groupCollapseButton: (folderText) => `//button[@data-testid='data-testid group-collapse-toggle'][following::div/h3[contains(., '${folderText}')]]`, ruleCollapseButton: 'button[aria-label=\'Expand row\']', goToFolderButton: (folderID, folderText) => locate('[aria-label="go to folder"]').withAttr({ href: `/graph/dashboards/f/${folderID}/${folderText}` }), managePermissionsButton: (folderID, folderText) => locate('[aria-label="manage permissions"]').withAttr({ href: `/graph/dashboards/f/${folderID}/${folderText}/permissions` }), confirmModal: 'button[aria-label=\'Confirm Modal Danger Button\']', cancelModal: locate('button').withText('Cancel'), + newEvaluationGroup: I.useDataQA('data-testid alert-rule new-evaluation-group-button'), + evaluationGroupCreate: I.useDataQA('data-testid alert-rule new-evaluation-group-create-button'), }, fields: { // searchDropdown returns a locator of a search input for a given label - searchDropdown: (option) => `//div[@id='${option}']`, - folderLocator: I.useDataQA('data-testid Folder picker select container'), + searchDropdown: (option) => `$${option}-select-input`, + folderLocator: I.useDataQA('data-testid folder-picker-input'), dropdownValue: (option) => `//*[@id='${option}']/div/div[1]/div[1]`, // resultsLocator returns item locator in a search dropdown based on a text - resultsLocator: (name) => `//div[@aria-label="Select option"]//div//span[text()="${name}"]`, + resultsLocator: (name) => locate('[class*="grafana-select-menu"]') + // resultsLocator: (name) => locate('//div[@aria-label="Select options menu"]') + .find(I.useDataQA(`${name}-select-option`)), inputField: (input) => `input[name='${input}']`, editRuleThreshold: 'input[name=\'evaluateFor\']', editRuleEvaluate: 'input[name=\'evaluateEvery\']', editRuleSeverity: I.useDataQA('label-value-1'), templatesLoader: locate('//div[@id=\'template\']').find('div').withText('Choose'), + evaluationGroupName: I.useDataQA('data-testid alert-rule new-evaluation-group-name'), }, messages: { noRulesFound: 'You haven`t created any alert rules yet', @@ -89,6 +94,9 @@ module.exports = { I.see(severity, this.fields.searchDropdown('severity')); this.searchAndSelectResult('severity', editedRule.severity); this.selectFolder(editedRule.folder); + I.click(this.buttons.newEvaluationGroup); + I.fillField(this.fields.evaluationGroupName, '1m'); + I.click(this.buttons.evaluationGroupCreate); }, async editPerconaAlert(ruleObj) { diff --git a/tests/ia/pages/api/rulesAPI.js b/tests/ia/pages/api/rulesAPI.js index a2bc78881..1780dabda 100644 --- a/tests/ia/pages/api/rulesAPI.js +++ b/tests/ia/pages/api/rulesAPI.js @@ -86,10 +86,10 @@ module.exports = { const headers = { Authorization: `Basic ${await I.getAuth()}` }; const resp = await I.sendDeleteRequest(`graph/api/ruler/grafana/api/v1/rules/${folderId}/${name}?subtype=cortex`, headers); - assert.ok( - resp.status === 202, - `Failed to remove alert rule. Response message is "${resp.data.message}"`, - ); + // assert.ok( + // resp.status === 202, + // `Failed to remove alert rule. Response message is "${resp.data.message}"`, + // ); }, async removeAllAlertRules() { diff --git a/tests/ia/pages/contactPointsPage.js b/tests/ia/pages/contactPointsPage.js index e5c5d9440..cb75018f7 100644 --- a/tests/ia/pages/contactPointsPage.js +++ b/tests/ia/pages/contactPointsPage.js @@ -29,7 +29,7 @@ module.exports = { }, }, elements: { - cPHeader: locate('h4').withText('Contact points'), + cPHeader: locate('h1').withText('Contact points'), cPTable: '$dynamic-table', deleteCPDialogHeader: locate('h2').withText('Delete contact point'), cannotdeleteCPDialogHeader: locate('h2').withText('Cannot delete contact point'), @@ -39,7 +39,8 @@ module.exports = { buttons: { newContactPoint: locate('button').find('span').withText('New contact point'), saveCP: locate('button').find('span').withText('Save contact point'), - deleteCP: (name) => `//*[@data-testid="row"][contains(., '${name}')]//button[@aria-label = 'Delete contact point']`, + deleteCP: locate('button').withText('Delete'), + moreMenu: (name) => locate(`//*[@data-testid="contact-point"][contains(., '${name}')]//button[@aria-label = 'More']`), confirmDeleteCP: locate('button').find('span').withText('Yes, delete'), editCP: (name) => `//*[@data-testid="row"][contains(., '${name}')]//a[@aria-label = 'Edit contact point']`, closeModal: locate('button').find('span').withText('Close'), @@ -80,8 +81,13 @@ module.exports = { await this.fillFields(name, type); }, + async openMoreMenu(name) { + I.waitForVisible(this.buttons.moreMenu(name), 10); + I.click(this.buttons.moreMenu(name)); + }, + async deleteCP(name) { - I.waitForVisible(this.buttons.deleteCP(name), 10); + await this.openMoreMenu(name); I.click(this.buttons.deleteCP(name)); }, diff --git a/tests/ia/pages/ruleTemplatesPage.js b/tests/ia/pages/ruleTemplatesPage.js index 2d3ce4e5c..b92466add 100644 --- a/tests/ia/pages/ruleTemplatesPage.js +++ b/tests/ia/pages/ruleTemplatesPage.js @@ -14,6 +14,8 @@ module.exports = { templateName: '//tr/td[1]', modalHeader: '$modal-header', modalWarning: '$alert-rule-name-warning', + templateRowByName: (name) => templateRow(name), + templateRowBySource: (source) => `//tr[descendant::div[contains(text(), "${source}")]]`, columnHeaderLocator: (columnHeaderText) => `//th[text()="${columnHeaderText}"]`, }, buttons: { diff --git a/tests/ia/ruleTemplates_test.js b/tests/ia/ruleTemplates_test.js index e1b94ec5c..1ec05561a 100644 --- a/tests/ia/ruleTemplates_test.js +++ b/tests/ia/ruleTemplates_test.js @@ -329,15 +329,10 @@ Scenario( Scenario( 'PMM-T884 Verify templates from Percona (SAAS) cannot be deleted or edited @ia', async ({ I, ruleTemplatesPage }) => { - const saasDeleteButton = ruleTemplatesPage.buttons - .deleteButtonBySource(ruleTemplatesPage.templateSources.saas); - const saasEditButton = ruleTemplatesPage.buttons - .editButtonBySource(ruleTemplatesPage.templateSources.saas); - ruleTemplatesPage.openRuleTemplatesTab(); - I.waitForElement(saasDeleteButton, 30); - I.seeAttributesOnElements(saasDeleteButton, { disabled: true }); - I.seeAttributesOnElements(saasEditButton, { disabled: true }); + I.waitForElement(ruleTemplatesPage.elements.templateRowBySource(ruleTemplatesPage.templateSources.saas), 30); + I.dontSeeElement(ruleTemplatesPage.buttons.deleteButtonBySource(ruleTemplatesPage.templateSources.saas), 30); + I.dontSeeElement(ruleTemplatesPage.buttons.editButtonBySource(ruleTemplatesPage.templateSources.saas), 30); }, ); @@ -376,12 +371,11 @@ Scenario( await I.verifyCommand('docker cp tests/ia/templates/template.txt pmm-server:/srv/alerting/templates'); ruleTemplatesPage.openRuleTemplatesTab(); - I.seeElement(editButton); - I.seeElement(ruleTemplatesPage.buttons.editButtonByName('Custom parameter template')); - I.dontSeeElement(ruleTemplatesPage.buttons.editButtonByName('Space in parameter')); + I.seeElement(ruleTemplatesPage.elements.templateRowByName('Custom parameter template')); + I.dontSeeElement(ruleTemplatesPage.buttons.templateRowByName('Space in parameter')); - I.seeElementsDisabled(editButton); - I.seeElementsDisabled(deleteButton); + I.dontSeeElement(editButton); + I.dontSeeElement(deleteButton); }, ); From 86afd3331ca52aa0488f3b48477120c06d0a8054 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Thu, 24 Oct 2024 19:10:03 +0300 Subject: [PATCH 27/33] PMM-13425 ia tests --- README.md | 2 +- package.json | 2 +- ...verifyPMMSettingsPageFunctionality_test.js | 2 +- tests/ia/README.md | 4 +- tests/ia/alertRules_test.js | 16 +- tests/ia/alerts_test.js | 16 +- tests/ia/common_test.js | 16 +- tests/ia/contactPoints_test.js | 10 +- tests/ia/pagination_test.js | 6 +- tests/ia/ruleTemplates_test.js | 168 +++++++++--------- 10 files changed, 124 insertions(+), 118 deletions(-) diff --git a/README.md b/README.md index 76de71f8b..63fd23bc3 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Execute command in the Project Root folder (e.g. Data from exporters is displayed at those dashboards) @dbaas DB as a Service functionality tests @grafana-pr Executed in Github Actions for PRs in percona-platform/grafana repository - @ia Integrated Alerting functionality tests + @alerting-fb Integrated Alerting functionality tests @instances Remote Instances addition functionality and checking that data appears from exporters @inventory Inventory functionality, removing nodes, services, etc. diff --git a/package.json b/package.json index b18969f13..f3e1d2860 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "lint:tests": "eslint --ext .js --fix tests/", "e2e": "npx codeceptjs run-multiple parallel --debug --steps --reporter mocha-multi -c pr.codecept.js --grep '(?=.*)^(?!.*@not-ui-pipeline)^(?!.*@not-pr-pipeline)'", - "e2e:ia": "npx codeceptjs run -c pr.codecept.js --grep '@ia'", + "e2e:ia": "npx codeceptjs run -c pr.codecept.js --grep '@alerting-fb'", "e2e:stt": "npx codeceptjs run -c pr.codecept.js --grep '@stt'", "e2e:dbaas": "npx codeceptjs run -c pr.codecept.js --grep '@dbaas'", "e2e:grafana-pr": "npx codeceptjs run -c pr.codecept.js --grep '@grafana-pr'" diff --git a/tests/configuration/verifyPMMSettingsPageFunctionality_test.js b/tests/configuration/verifyPMMSettingsPageFunctionality_test.js index 7669f03cd..ef38a4c18 100644 --- a/tests/configuration/verifyPMMSettingsPageFunctionality_test.js +++ b/tests/configuration/verifyPMMSettingsPageFunctionality_test.js @@ -74,7 +74,7 @@ Scenario.skip( ).retry(2); Scenario( - 'PMM-T532 PMM-T533 PMM-T536 - Verify user can disable/enable IA in Settings @ia @settings', + 'PMM-T532 PMM-T533 PMM-T536 - Verify user can disable/enable IA in Settings @alerting-fb @settings', async ({ I, pmmSettingsPage, settingsAPI, adminPage, }) => { diff --git a/tests/ia/README.md b/tests/ia/README.md index 06bd56d2c..8ad984b27 100644 --- a/tests/ia/README.md +++ b/tests/ia/README.md @@ -29,10 +29,10 @@ Shut down webhook server command: `docker-compose -f docker-compose-webhook.yml ### Command to execute all Integrated Alerting tests: -`npx codeceptjs run -c pr.codecept.js --grep '@ia'` +`npx codeceptjs run -c pr.codecept.js --grep '@alerting-fb'` ### Execute Integrated Alerting tests in Jenkins * Job name - `pmm2-ui-tests` -* tag - `@ia` +* tag - `@alerting-fb` * run tagged day - `yes` * clients not needed diff --git a/tests/ia/alertRules_test.js b/tests/ia/alertRules_test.js index 488b17219..73d10f2fd 100644 --- a/tests/ia/alertRules_test.js +++ b/tests/ia/alertRules_test.js @@ -29,7 +29,7 @@ After(async () => { }); Scenario( - 'PMM-T1384 Verify empty alert rules list @ia @grafana-pr', + 'PMM-T1384 Verify empty alert rules list @alerting-fb @grafana-pr', async ({ I, alertRulesPage }) => { alertRulesPage.openAlertRulesTab(); I.waitForText(alertRulesPage.messages.noRulesFound, 10, alertRulesPage.elements.noRules); @@ -42,7 +42,7 @@ Scenario( ).retry(0); Scenario( - 'PMM-T1385 Verify alert rules elements @ia @grafana-pr', + 'PMM-T1385 Verify alert rules elements @alerting-fb @grafana-pr', async ({ I, alertRulesPage, rulesAPI }) => { const ruleName = 'testRule'; const ruleFolder = 'PostgreSQL'; @@ -73,7 +73,7 @@ Scenario( ); Scenario( - 'PMM-T1392 Verify fields dynamically change value when template is changed @ia @grafana-pr', + 'PMM-T1392 Verify fields dynamically change value when template is changed @alerting-fb @grafana-pr', async ({ I, alertRulesPage }) => { // TODO: https://jira.percona.com/browse/PMM-10860 name doesn't change alertRulesPage.openAlertRulesTab(); @@ -90,7 +90,7 @@ Scenario( ); Scenario( - 'PMM-T1420 Verify user can create Percona templated alert @ia @alerting-fb', + 'PMM-T1420 Verify user can create Percona templated alert @alerting-fb', async ({ I, alertRulesPage, rulesAPI }) => { const rule = page.rules[15]; const newRule = page.rules[0]; @@ -111,7 +111,7 @@ Scenario( // TODO: unskip in scope of https://perconadev.atlassian.net/browse/PMM-12938 Scenario.skip( - 'PMM-T2282 Verfied Alerting is able to monitor for "PMM Agent Down" @ia @alerting-fb', + 'PMM-T2282 Verfied Alerting is able to monitor for "PMM Agent Down" @alerting-fb', async ({ I, alertRulesPage, rulesAPI }) => { const rule = page.rules[29]; const newRule = page.rules[30]; @@ -139,7 +139,7 @@ Scenario.skip( // TODO: check ovf failure Scenario( - 'PMM-T1430 Verify user can edit Percona templated alert @ia @not-ovf @alerting-fb', + 'PMM-T1430 Verify user can edit Percona templated alert @alerting-fb @not-ovf', async ({ I, alertRulesPage, rulesAPI, }) => { @@ -165,7 +165,7 @@ Scenario( ); Scenario( - 'PMM-T1433 Verify user can delete Percona templated alert @ia @alerting-fb', + 'PMM-T1433 Verify user can delete Percona templated alert @alerting-fb', async ({ I, alertRulesPage, rulesAPI, iaCommon, }) => { @@ -191,7 +191,7 @@ Scenario( // nightly candidate // FIXME: flaky test fix and unskip Scenario.skip( - 'PMM-T1434 Verify validation errors when creating new alert rule @ia @grafana-pr', + 'PMM-T1434 Verify validation errors when creating new alert rule @alerting-fb @grafana-pr', async ({ I, alertRulesPage, }) => { diff --git a/tests/ia/alerts_test.js b/tests/ia/alerts_test.js index 937d6ac51..3d53d33f7 100644 --- a/tests/ia/alerts_test.js +++ b/tests/ia/alerts_test.js @@ -42,7 +42,7 @@ AfterSuite(async ({ rulesAPI, I }) => { }); Scenario.skip( - 'PMM-T1482 Verify fired alert @ia', + 'PMM-T1482 Verify fired alert @alerting-fb', async ({ I, alertsPage, alertsAPI }) => { await alertsAPI.waitForAlerts(24, 1); await I.amOnPage(alertsPage.url); @@ -60,7 +60,7 @@ Scenario.skip( ); Scenario.skip( - 'PMM-T1494 PMM-T1495 Verify fired alert in Pager Duty and Webhook @ia', + 'PMM-T1494 PMM-T1495 Verify fired alert in Pager Duty and Webhook @alerting-fb', async ({ I, alertsAPI, rulesAPI }) => { const file = './testdata/ia/scripts/alert.txt'; const alertUID = await rulesAPI.getAlertUID(ruleName, ruleFolder); @@ -76,7 +76,7 @@ Scenario.skip( ); Scenario.skip( - 'PMM-T1496 PMM-T1497 Verify it is possible to silence and unsilence alert @ia', + 'PMM-T1496 PMM-T1497 Verify it is possible to silence and unsilence alert @alerting-fb', async ({ I, alertsPage, alertmanagerAPI, }) => { @@ -94,7 +94,7 @@ Scenario.skip( ); Scenario.skip( - 'PMM-T1498 Verify firing alerts dissappear when the condition is fixed @ia', + 'PMM-T1498 Verify firing alerts dissappear when the condition is fixed @alerting-fb', async ({ I, alertsPage, alertRulesPage, }) => { @@ -113,7 +113,7 @@ Scenario.skip( // FIXME: Skip until https://jira.percona.com/browse/PMM-11130 is fixed Scenario.skip( - 'PMM-T659 Verify alerts are deleted after deleting rules @ia', + 'PMM-T659 Verify alerts are deleted after deleting rules @alerting-fb', async ({ I, alertsPage, rulesAPI }) => { // Deleting rules await rulesAPI.removeAllAlertRules(); @@ -124,7 +124,7 @@ Scenario.skip( ); Scenario.skip( - 'PMM-T1499 Verify an alert with non-existing filter (label) does not show up in list @ia', + 'PMM-T1499 Verify an alert with non-existing filter (label) does not show up in list @alerting-fb', async ({ I, alertsPage, rulesAPI }) => { await rulesAPI.removeAllAlertRules(); const wrongFilterRule = { @@ -146,7 +146,7 @@ Scenario.skip( ); Scenario.skip( - 'PMM-T564 Verify fired alert severity colors @ia', + 'PMM-T564 Verify fired alert severity colors @alerting-fb', async ({ I, alertsPage, rulesAPI, alertsAPI, }) => { @@ -172,7 +172,7 @@ Scenario.skip( ); Scenario.skip( - 'PMM-T1467 Verify empty Fired alerts list @ia', + 'PMM-T1467 Verify empty Fired alerts list @alerting-fb', async ({ I, alertsPage, rulesAPI }) => { await rulesAPI.removeAllAlertRules(); I.amOnPage(alertsPage.url); diff --git a/tests/ia/common_test.js b/tests/ia/common_test.js index f755a11d9..2d156f4cb 100644 --- a/tests/ia/common_test.js +++ b/tests/ia/common_test.js @@ -8,7 +8,7 @@ Before(async ({ I, rulesAPI }) => { }); Scenario( - 'PMM-T643 Verify message about disabled IA @ia @alerting-fb', + 'PMM-T643 Verify message about disabled IA @alerting-fb', async ({ I, pmmSettingsPage, codeceptjsConfig, }) => { @@ -26,7 +26,7 @@ Scenario( Scenario( 'PMM-T481 Verify IA tab bar, ' + 'PMM-T620 Verify after reloading the page user is on the same IA tab, ' - + 'PMM-T776 Verify that user is able to see valid HTML Title on alerts page @ia @alerting-fb', + + 'PMM-T776 Verify that user is able to see valid HTML Title on alerts page @alerting-fb', async ({ I, alertRulesPage, ruleTemplatesPage, contactPointsPage, nPoliciesPage, silencesPage, alertGroupsPage, aiAdminPage, }) => { @@ -44,18 +44,17 @@ Scenario( }; verifyTitle('Fired alerts'); - await iaCommon.openAndVerifyTab( + iaCommon.openAndVerifyTab( iaCommon.tabNames.ruleTemplates, ruleTemplatesPage.buttons.openAddTemplateModal, ruleTemplatesPage.url, ); verifyTitle('Alert rule templates'); - await iaCommon.openAndVerifyTab(iaCommon.tabNames.alertRules, alertRulesPage.buttons.newAlertRule, alertRulesPage.url); + iaCommon.openAndVerifyTab(iaCommon.tabNames.alertRules, alertRulesPage.buttons.newAlertRule, alertRulesPage.url); verifyTitle('Alert rules'); - await iaCommon - .openAndVerifyTab(iaCommon.tabNames.contactPoints, contactPointsPage.buttons.newContactPoint, contactPointsPage.url); + iaCommon.openAndVerifyTab(iaCommon.tabNames.contactPoints, contactPointsPage.buttons.newContactPoint, contactPointsPage.url); verifyTitle('Contact points'); - await iaCommon.openAndVerifyTab(iaCommon.tabNames.notificationPolicies, nPoliciesPage.buttons.newPolicy, nPoliciesPage.url); + iaCommon.openAndVerifyTab(iaCommon.tabNames.notificationPolicies, nPoliciesPage.buttons.newPolicy, nPoliciesPage.url); verifyTitle('Notification policies'); // PMM-T620 @@ -64,8 +63,7 @@ Scenario( await iaCommon.openAndVerifyTab(iaCommon.tabNames.silences, silencesPage.buttons.newSilence, silencesPage.url); verifyTitle('Silences'); - await iaCommon - .openAndVerifyTab(iaCommon.tabNames.alertGroups, alertGroupsPage.elements.groupByContainer, alertGroupsPage.url); + await iaCommon.openAndVerifyTab(iaCommon.tabNames.alertGroups, alertGroupsPage.elements.groupByContainer, alertGroupsPage.url); verifyTitle('Alert groups'); await iaCommon.openAndVerifyTab(iaCommon.tabNames.admin, aiAdminPage.elements.configTextarea, aiAdminPage.url); verifyTitle('Admin'); diff --git a/tests/ia/contactPoints_test.js b/tests/ia/contactPoints_test.js index 527b9ded0..ba6ed0572 100644 --- a/tests/ia/contactPoints_test.js +++ b/tests/ia/contactPoints_test.js @@ -14,7 +14,7 @@ Before(async ({ I }) => { Data(contactPoints).Scenario( 'PMM-T1703 Verify Slack contact point can be created, ' - + 'PMM-T1709 Verify Webhook contact point can be created @ia', + + 'PMM-T1709 Verify Webhook contact point can be created @alerting-fb', async ({ I, current }) => { await contactPointsPage.openContactPointsTab(); await contactPointsPage.createCP(current.name, current.type); @@ -25,7 +25,7 @@ Data(contactPoints).Scenario( ); Data(contactPoints).Scenario( - 'PMM-T1707 Verify Slack contact point can be edited @ia', + 'PMM-T1707 Verify Slack contact point can be edited @alerting-fb', async ({ I, current }) => { await contactPointsPage.openContactPointsTab(); await contactPointsPage.editCP(current.name); @@ -37,7 +37,7 @@ Data(contactPoints).Scenario( ); Scenario( - 'PMM-T1706 Verify default contact point cannot be deleted @ia', + 'PMM-T1706 Verify default contact point cannot be deleted @alerting-fb', async ({ I }) => { await contactPointsPage.openContactPointsTab(); await contactPointsPage.openMoreMenu('default'); @@ -47,7 +47,7 @@ Scenario( ); Data(contactPoints).Scenario( - 'PMM-T1704 Verify Slack contact point can be deleted @ia', + 'PMM-T1704 Verify Slack contact point can be deleted @alerting-fb', async ({ I, current }) => { const name = current.name + editedCPName; @@ -63,7 +63,7 @@ Data(contactPoints).Scenario( Scenario( 'PMM-T1710 Verify saving a contact point when required info is missing, ' - + 'PMM-T1711 Verify contact point test @ia', + + 'PMM-T1711 Verify contact point test @alerting-fb', async ({ I, iaCommon }) => { await contactPointsPage.openContactPointsTab(); I.waitForVisible(contactPointsPage.buttons.newContactPoint, 10); diff --git a/tests/ia/pagination_test.js b/tests/ia/pagination_test.js index aea1920b1..5e1ede83f 100644 --- a/tests/ia/pagination_test.js +++ b/tests/ia/pagination_test.js @@ -13,7 +13,7 @@ After(async ({ templatesAPI }) => { }); Scenario( - 'PMM-T632 PMM-T697 PMM-T701 PMM-T1251 Verify Pagination navigation @ia @grafana-pr', + 'PMM-T632 PMM-T697 PMM-T701 PMM-T1251 Verify Pagination navigation @alerting-fb @grafana-pr', async ({ I, iaCommon, }) => { @@ -144,7 +144,7 @@ Scenario( ); Scenario( - 'PMM-T662 PMM-T698 PMM-T702 PMM-T631 PMM-T1251 Pagination rows per page persistence @ia', + 'PMM-T662 PMM-T698 PMM-T702 PMM-T631 PMM-T1251 Pagination rows per page persistence @alerting-fb', async ({ I, iaCommon, }) => { @@ -219,7 +219,7 @@ Scenario( ); Scenario( - 'PMM-T631 PMM-T633 PMM-T1251 Changing rows per page resets view to 1 page @ia', + 'PMM-T631 PMM-T633 PMM-T1251 Changing rows per page resets view to 1 page @alerting-fb', async ({ I, iaCommon, templatesAPI, }) => { diff --git a/tests/ia/ruleTemplates_test.js b/tests/ia/ruleTemplates_test.js index 1ec05561a..544ae872a 100644 --- a/tests/ia/ruleTemplates_test.js +++ b/tests/ia/ruleTemplates_test.js @@ -38,7 +38,7 @@ Before(async ({ templatesAPI }) => { // TODO: Unskip after we bring back built-in templates Scenario.skip( - 'PMM-T510 Verify built-in rule templates are non-editable @ia @grafana-pr', + 'PMM-T510 Verify built-in rule templates are non-editable @alerting-fb @grafana-pr', async ({ I, ruleTemplatesPage }) => { const editButton = ruleTemplatesPage.buttons .editButtonBySource(ruleTemplatesPage.templateSources.builtin); @@ -53,7 +53,7 @@ Scenario.skip( ); Scenario( - 'Verify rule templates list elements @ia @grafana-pr', + 'Verify rule templates list elements @alerting-fb @grafana-pr', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; @@ -79,7 +79,7 @@ Scenario( ); Scenario( - 'Add rule template modal elements @ia @grafana-pr', + 'Add rule template modal elements @alerting-fb @grafana-pr', async ({ I, ruleTemplatesPage }) => { ruleTemplatesPage.openRuleTemplatesTab(); I.click(ruleTemplatesPage.buttons.openAddTemplateModal); @@ -92,70 +92,72 @@ Scenario( ); // nightly candidate -Data(units).Scenario( - 'PMM-T500 PMM-T595 PMM-T596 Add rule templates with different units, empty range @ia', - async ({ - I, ruleTemplatesPage, templatesAPI, current, - }) => { - const [templateName, fileContent, id] = await ruleTemplatesPage.ruleTemplate - .templateNameAndContent(ruleTemplatesPage.ruleTemplate.inputFilePath); - const editButton = ruleTemplatesPage.buttons - .editButtonByName(templateName); - const deleteButton = ruleTemplatesPage.buttons - .deleteButtonByName(templateName); - - const newFileContent = fileContent - .replace('unit: \'%\'', `unit: '${current.unit}'`) - .replace('range: [0, 100]', `range: ${current.range}`); - - ruleTemplatesPage.openRuleTemplatesTab(); - - I.click(ruleTemplatesPage.buttons.openAddTemplateModal); - I.fillField(ruleTemplatesPage.fields.templateInput, newFileContent); - I.click(ruleTemplatesPage.buttons.addTemplate); - if (current.unit !== '*') { - I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); +Data(units) + .Scenario( + 'PMM-T500 PMM-T595 PMM-T596 Add rule templates with different units, empty range @alerting-fb', + async ({ + I, ruleTemplatesPage, templatesAPI, current, + }) => { + const [templateName, fileContent, id] = await ruleTemplatesPage.ruleTemplate + .templateNameAndContent(ruleTemplatesPage.ruleTemplate.inputFilePath); + const editButton = ruleTemplatesPage.buttons + .editButtonByName(templateName); + const deleteButton = ruleTemplatesPage.buttons + .deleteButtonByName(templateName); - // Check that Edit and Delete buttons are enabled - I.waitForEnabled(editButton); - I.waitForEnabled(deleteButton); + const newFileContent = fileContent + .replace('unit: \'%\'', `unit: '${current.unit}'`) + .replace('range: [0, 100]', `range: ${current.range}`); - await templatesAPI.removeTemplate(id); - } else { - I.verifyPopUpMessage(ruleTemplatesPage.messages.failedToParse); - } - }, -); - -Data(templates).Scenario( - 'PMM-T482 PMM-T499 PMM-T766 PMM-T758 PMM-T766 PMM-T767 PMM-T931 Upload rule templates @ia', - async ({ I, ruleTemplatesPage, current }) => { - const { path } = current; - const validFile = !current.error; - const [templateName] = await ruleTemplatesPage.ruleTemplate.templateNameAndContent(path); - const expectedSourceLocator = ruleTemplatesPage - .getSourceLocator(templateName, ruleTemplatesPage.templateSources.ui); - const editButton = ruleTemplatesPage.buttons - .editButtonBySource(ruleTemplatesPage.templateSources.ui); + ruleTemplatesPage.openRuleTemplatesTab(); - ruleTemplatesPage.openRuleTemplatesTab(); - I.click(ruleTemplatesPage.buttons.openAddTemplateModal); - I.attachFile(ruleTemplatesPage.fields.fileInput, path); - await ruleTemplatesPage.verifyInputContent(path); - I.click(ruleTemplatesPage.buttons.addTemplate); + I.click(ruleTemplatesPage.buttons.openAddTemplateModal); + I.fillField(ruleTemplatesPage.fields.templateInput, newFileContent); + I.click(ruleTemplatesPage.buttons.addTemplate); + if (current.unit !== '*') { + I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); + + // Check that Edit and Delete buttons are enabled + I.waitForEnabled(editButton); + I.waitForEnabled(deleteButton); + + await templatesAPI.removeTemplate(id); + } else { + I.verifyPopUpMessage(ruleTemplatesPage.messages.failedToParse); + } + }, + ); + +Data(templates) + .Scenario( + 'PMM-T482 PMM-T499 PMM-T766 PMM-T758 PMM-T766 PMM-T767 PMM-T931 Upload rule templates @alerting-fb', + async ({ I, ruleTemplatesPage, current }) => { + const { path } = current; + const validFile = !current.error; + const [templateName] = await ruleTemplatesPage.ruleTemplate.templateNameAndContent(path); + const expectedSourceLocator = ruleTemplatesPage + .getSourceLocator(templateName, ruleTemplatesPage.templateSources.ui); + const editButton = ruleTemplatesPage.buttons + .editButtonBySource(ruleTemplatesPage.templateSources.ui); - if (validFile) { - I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); - I.waitForVisible(expectedSourceLocator, 30); - I.waitForEnabled(editButton); - } else { - I.verifyPopUpMessage(current.error); - } - }, -); + ruleTemplatesPage.openRuleTemplatesTab(); + I.click(ruleTemplatesPage.buttons.openAddTemplateModal); + I.attachFile(ruleTemplatesPage.fields.fileInput, path); + await ruleTemplatesPage.verifyInputContent(path); + I.click(ruleTemplatesPage.buttons.addTemplate); + + if (validFile) { + I.verifyPopUpMessage(ruleTemplatesPage.messages.successfullyAdded); + I.waitForVisible(expectedSourceLocator, 30); + I.waitForEnabled(editButton); + } else { + I.verifyPopUpMessage(current.error); + } + }, + ); Scenario( - '@PMM-T1785 Bulk rule templates upload @ia', + '@PMM-T1785 Bulk rule templates upload @alerting-fb', async ({ I, ruleTemplatesPage }) => { const path = 'tests/ia/templates/multiple-templates.yml'; const templates = await ruleTemplatesPage.ruleTemplate.parseTemplates(path); @@ -174,13 +176,13 @@ Scenario( .editButtonBySource(ruleTemplatesPage.templateSources.ui); I.waitForVisible(expectedSourceLocator, 30); - I.seeElement(editButton); + I.waitForEnabled(editButton); } }, ); Scenario( - '@PMM-T1786 Edit bulk uploaded rule template @ia', + '@PMM-T1786 Edit bulk uploaded rule template @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = 'tests/ia/templates/multiple-templates.yml'; const templates = await ruleTemplatesPage.ruleTemplate.parseTemplates(path); @@ -217,7 +219,7 @@ Scenario( ); Scenario( - '@PMM-T1787 Delete bulk uploaded rule template @ia', + '@PMM-T1787 Delete bulk uploaded rule template @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = 'tests/ia/templates/multiple-templates.yml'; const templates = await ruleTemplatesPage.ruleTemplate.parseTemplates(path); @@ -249,7 +251,7 @@ Scenario( ); Scenario( - 'PMM-T501 Upload duplicate rule template @ia @grafana-pr', + 'PMM-T501 Upload duplicate rule template @alerting-fb @grafana-pr', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; const [, , id] = await ruleTemplatesPage.ruleTemplate.templateNameAndContent(path); @@ -267,7 +269,7 @@ Scenario( ); Scenario( - 'PMM-T483 PMM-T699 Verify user can edit UI-created IA rule template @ia @grafana-pr @alerting-fb', + 'PMM-T483 PMM-T699 Verify user can edit UI-created IA rule template @grafana-pr @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; const [templateName, fileContent, id] = await ruleTemplatesPage.ruleTemplate @@ -298,7 +300,7 @@ Scenario( ); Scenario( - 'PMM-T562 Verify user can delete User-defined (UI) rule templates @ia @grafana-pr @alerting-fb', + 'PMM-T562 Verify user can delete User-defined (UI) rule templates @grafana-pr @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; const [templateName] = await ruleTemplatesPage.ruleTemplate @@ -327,22 +329,27 @@ Scenario( ); Scenario( - 'PMM-T884 Verify templates from Percona (SAAS) cannot be deleted or edited @ia', + 'PMM-T884 Verify templates from Percona (SAAS) cannot be deleted or edited @alerting-fb', async ({ I, ruleTemplatesPage }) => { + const saasDeleteButton = ruleTemplatesPage.buttons + .deleteButtonBySource(ruleTemplatesPage.templateSources.saas); + const saasEditButton = ruleTemplatesPage.buttons + .editButtonBySource(ruleTemplatesPage.templateSources.saas); + ruleTemplatesPage.openRuleTemplatesTab(); - I.waitForElement(ruleTemplatesPage.elements.templateRowBySource(ruleTemplatesPage.templateSources.saas), 30); - I.dontSeeElement(ruleTemplatesPage.buttons.deleteButtonBySource(ruleTemplatesPage.templateSources.saas), 30); - I.dontSeeElement(ruleTemplatesPage.buttons.editButtonBySource(ruleTemplatesPage.templateSources.saas), 30); + I.waitForElement(saasDeleteButton, 30); + I.seeAttributesOnElements(saasDeleteButton, { disabled: true }); + I.seeAttributesOnElements(saasEditButton, { disabled: true }); }, ); Scenario( - 'PMM-T553 Verify rule template can be deleted if there is a rule based on it @ia', + 'PMM-T553 Verify rule template can be deleted if there is a rule based on it @alerting-fb', async ({ I, ruleTemplatesPage, templatesAPI, rulesAPI, }) => { const path = ruleTemplatesPage.ruleTemplate.paths.yaml; - const [templateName] = await ruleTemplatesPage.ruleTemplate + const [templateName, , id] = await ruleTemplatesPage.ruleTemplate .templateNameAndContent(path); const deleteButton = ruleTemplatesPage.buttons .deleteButtonByName(templateName); @@ -359,7 +366,7 @@ Scenario( ); Scenario( - 'PMM-T825 PMM-T821 Verify User can add Alert rule template in the file system @not-ovf @ia', + 'PMM-T825 PMM-T821 Verify User can add Alert rule template in the file system @not-ovf @alerting-fb', async ({ I, ruleTemplatesPage }) => { const editButton = ruleTemplatesPage.buttons .editButtonBySource(ruleTemplatesPage.templateSources.file); @@ -371,16 +378,17 @@ Scenario( await I.verifyCommand('docker cp tests/ia/templates/template.txt pmm-server:/srv/alerting/templates'); ruleTemplatesPage.openRuleTemplatesTab(); - I.seeElement(ruleTemplatesPage.elements.templateRowByName('Custom parameter template')); - I.dontSeeElement(ruleTemplatesPage.buttons.templateRowByName('Space in parameter')); + I.seeElement(editButton); + I.seeElement(ruleTemplatesPage.buttons.editButtonByName('Custom parameter template')); + I.dontSeeElement(ruleTemplatesPage.buttons.editButtonByName('Space in parameter')); - I.dontSeeElement(editButton); - I.dontSeeElement(deleteButton); + I.seeElementsDisabled(editButton); + I.seeElementsDisabled(deleteButton); }, ); Scenario( - 'PMM-T1126 - Verify there are no Templates from Percona if Telemetry is disabled @ia', + 'PMM-T1126 - Verify there are no Templates from Percona if Telemetry is disabled @alerting-fb', async ({ I, settingsAPI, ruleTemplatesPage }) => { const editButton = ruleTemplatesPage.buttons .editButtonBySource(ruleTemplatesPage.templateSources.saas); @@ -400,7 +408,7 @@ Scenario( ); Scenario( - '@PMM-T1514 Verify that alert rule templates has only 1 exit button @ia', + '@PMM-T1514 Verify that alert rule templates has only 1 exit button @alerting-fb', async ({ I, ruleTemplatesPage, alertRulesPage }) => { ruleTemplatesPage.openRuleTemplatesTab(); ruleTemplatesPage.openAddDialog(await I.grabTextFrom(ruleTemplatesPage.elements.templateName)); From eaa668928a4ae96091be1772caa5005dce5d4657 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 1 Nov 2024 12:42:19 +0200 Subject: [PATCH 28/33] PMM-7 disconnect tests tweaks --- tests/configuration/verifyPMMServerDisconnect_test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/configuration/verifyPMMServerDisconnect_test.js b/tests/configuration/verifyPMMServerDisconnect_test.js index 08c5af6d4..8747dd398 100644 --- a/tests/configuration/verifyPMMServerDisconnect_test.js +++ b/tests/configuration/verifyPMMServerDisconnect_test.js @@ -8,11 +8,11 @@ const serverImage = process.env.DOCKER_VERSION || 'perconalab/pmm-server:3-dev-l BeforeSuite(async ({ I }) => { await I.verifyCommand(`PMM_SERVER_IMAGE=${serverImage} docker compose -f docker-compose-disconnect.yml up -d pmm-server-disconnect`); - await I.asyncWaitFor(async () => await I.verifyCommand(`echo $(curl -s -o /dev/null -w '%{http_code}' 127.0.0.1:${pmmServerPort}/ping)`) === '200', 100); + await I.asyncWaitFor(async () => await I.verifyCommand(`echo $(curl -s -o /dev/null -w '%{http_code}' 127.0.0.1:${pmmServerPort}/ping)`) === '200', 60); await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d pmm-client'); await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d mysql5.7'); clientServerNetwork = await I.verifyCommand('docker inspect pmm-client-disconnect -f \'{{range $k, $v := .NetworkSettings.Networks}}{{printf "%s\\n" $k}}{{end}}\' | grep -o \'.*server-network\''); - await I.asyncWaitFor(async () => await I.verifyCommand('echo $(docker container logs mysql-disconnect-5.7 2>&1 | grep "Server hostname (bind-address)")') !== '', 100); + await I.asyncWaitFor(async () => await I.verifyCommand('echo $(docker container logs mysql-disconnect-5.7 2>&1 | grep "Server hostname (bind-address)")') !== '', 60); await I.verifyCommand('docker exec pmm-client-disconnect pmm-admin add mysql --username=root --password=7B*53@lCdflR --host=mysql-disconnect-5.7 --port=3306 --query-source=perfschema mysql-disconnect-5.7'); // wait for the data to be scraped from db I.wait(60); @@ -28,7 +28,7 @@ AfterSuite(async ({ I }) => { const withCustomBaseUrl = (url) => `${basePmmUrl}${url}`; -Scenario( +Scenario.only( '@PMM-T1442 Verify metrics are saved if PMM server was offline @disconnect', async ({ I, dashboardPage }) => { await I.amOnPage(withCustomBaseUrl(dashboardPage.mySQLInstanceOverview.url)); From 6cbdfc0724b4b19d34612f780160f834d8b6d6be Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 1 Nov 2024 12:45:02 +0200 Subject: [PATCH 29/33] PMM-7 clickhouse tests tweaks --- docker-compose-clickhouse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-clickhouse.yml b/docker-compose-clickhouse.yml index 7ed7a6cbe..32cb8abbd 100644 --- a/docker-compose-clickhouse.yml +++ b/docker-compose-clickhouse.yml @@ -31,7 +31,7 @@ services: condition: service_healthy environment: - PMM_AGENT_SETUP=1 - - PMM_AGENT_SERVER_ADDRESS=pmm-server-external-clickhouse + - PMM_AGENT_SERVER_ADDRESS=pmm-server-external-clickhouse:8443 - PMM_AGENT_SERVER_USERNAME=admin - PMM_AGENT_SERVER_PASSWORD=admin - PMM_AGENT_PORTS_MIN=41000 From 7fd4f21c8b074b9cfed8d2bf0428cce0d81c5814 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 1 Nov 2024 12:58:07 +0200 Subject: [PATCH 30/33] PMM-7 clickhouse tests tweaks --- docker-compose-disconnect.yml | 6 +++--- tests/configuration/verifyPMMServerDisconnect_test.js | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docker-compose-disconnect.yml b/docker-compose-disconnect.yml index 6c46666fe..df820fe39 100644 --- a/docker-compose-disconnect.yml +++ b/docker-compose-disconnect.yml @@ -55,9 +55,9 @@ services: - server-network - mysql-network - mysql5.7: - container_name: mysql-disconnect-5.7 - image: mysql:5.7 + ps8: + container_name: ps8 + image: percona:8.0 command: --default-authentication-plugin=mysql_native_password restart: always environment: diff --git a/tests/configuration/verifyPMMServerDisconnect_test.js b/tests/configuration/verifyPMMServerDisconnect_test.js index 8747dd398..fb18751fe 100644 --- a/tests/configuration/verifyPMMServerDisconnect_test.js +++ b/tests/configuration/verifyPMMServerDisconnect_test.js @@ -10,10 +10,10 @@ BeforeSuite(async ({ I }) => { await I.verifyCommand(`PMM_SERVER_IMAGE=${serverImage} docker compose -f docker-compose-disconnect.yml up -d pmm-server-disconnect`); await I.asyncWaitFor(async () => await I.verifyCommand(`echo $(curl -s -o /dev/null -w '%{http_code}' 127.0.0.1:${pmmServerPort}/ping)`) === '200', 60); await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d pmm-client'); - await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d mysql5.7'); + await I.verifyCommand('docker compose -f docker-compose-disconnect.yml up -d ps8'); clientServerNetwork = await I.verifyCommand('docker inspect pmm-client-disconnect -f \'{{range $k, $v := .NetworkSettings.Networks}}{{printf "%s\\n" $k}}{{end}}\' | grep -o \'.*server-network\''); - await I.asyncWaitFor(async () => await I.verifyCommand('echo $(docker container logs mysql-disconnect-5.7 2>&1 | grep "Server hostname (bind-address)")') !== '', 60); - await I.verifyCommand('docker exec pmm-client-disconnect pmm-admin add mysql --username=root --password=7B*53@lCdflR --host=mysql-disconnect-5.7 --port=3306 --query-source=perfschema mysql-disconnect-5.7'); + I.wait(20); + await I.verifyCommand('docker exec pmm-client-disconnect pmm-admin add mysql --username=root --password=7B*53@lCdflR --host=ps8 --port=3306 --query-source=perfschema ps8'); // wait for the data to be scraped from db I.wait(60); }); @@ -28,7 +28,7 @@ AfterSuite(async ({ I }) => { const withCustomBaseUrl = (url) => `${basePmmUrl}${url}`; -Scenario.only( +Scenario( '@PMM-T1442 Verify metrics are saved if PMM server was offline @disconnect', async ({ I, dashboardPage }) => { await I.amOnPage(withCustomBaseUrl(dashboardPage.mySQLInstanceOverview.url)); From 3b24924b950ba017eda56fb7cb9ae38a05bd176c Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 1 Nov 2024 13:33:51 +0200 Subject: [PATCH 31/33] PMM-7 disconnect tests tweaks --- tests/configuration/verifyPMMServerDisconnect_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/configuration/verifyPMMServerDisconnect_test.js b/tests/configuration/verifyPMMServerDisconnect_test.js index fb18751fe..48dacbb64 100644 --- a/tests/configuration/verifyPMMServerDisconnect_test.js +++ b/tests/configuration/verifyPMMServerDisconnect_test.js @@ -43,7 +43,7 @@ Scenario( await I.amOnPage(withCustomBaseUrl(`${dashboardPage.mySQLInstanceOverview.clearUrl}?orgId=1&from=now-3m&to=now-1m`)); await dashboardPage.waitForDashboardOpened(); await dashboardPage.expandEachDashboardRow(); - await dashboardPage.verifyThereAreNoGraphsWithoutData(1); + await dashboardPage.verifyThereAreNoGraphsWithoutData(2); I.dontSeeElement(dashboardPage.fields.metricPanelNa('Services panel')); }, ); @@ -63,7 +63,7 @@ Scenario( await I.amOnPage(withCustomBaseUrl(`${dashboardPage.mySQLInstanceOverview.clearUrl}?orgId=1&from=now-3m&to=now-1m`)); await dashboardPage.waitForDashboardOpened(); await dashboardPage.expandEachDashboardRow(); - await dashboardPage.verifyThereAreNoGraphsWithoutData(1); + await dashboardPage.verifyThereAreNoGraphsWithoutData(2); I.dontSeeElement(dashboardPage.fields.metricPanelNa('Services panel')); }, ); From 3549de7fcea15b99f13ea31ce77eae15cb84e6f8 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 1 Nov 2024 14:52:44 +0200 Subject: [PATCH 32/33] PMM-7 clickhouse tests tweaks --- docker-compose-clickhouse.yml | 6 +++--- tests/QAN/externalClickhouse_test.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose-clickhouse.yml b/docker-compose-clickhouse.yml index 32cb8abbd..f78a5d69d 100644 --- a/docker-compose-clickhouse.yml +++ b/docker-compose-clickhouse.yml @@ -43,9 +43,9 @@ services: - PMM_AGENT_SETUP_NODE_TYPE=container restart: on-failure - mysql5.7: - container_name: mysql5.7 - image: mysql:5.7 + ps8: + container_name: ps8 + image: percona:8 command: --default-authentication-plugin=mysql_native_password restart: always environment: diff --git a/tests/QAN/externalClickhouse_test.js b/tests/QAN/externalClickhouse_test.js index 787b6eed5..47b557858 100644 --- a/tests/QAN/externalClickhouse_test.js +++ b/tests/QAN/externalClickhouse_test.js @@ -5,12 +5,12 @@ Feature('External Clickhouse Tests'); // Address of PMM with external clickhouse created with docker compose. const pmmServerPort = '8081'; const basePmmUrl = `http://127.0.0.1:${pmmServerPort}/`; -const dockerVersion = process.env.DOCKER_VERSION || 'perconalab/pmm-server:dev-latest'; +const dockerVersion = process.env.DOCKER_VERSION || 'perconalab/pmm-server:3-dev-latest'; BeforeSuite(async ({ I }) => { await I.verifyCommand(`PMM_SERVER_IMAGE=${dockerVersion} docker-compose -f docker-compose-clickhouse.yml up -d`); await I.wait(30); - await I.verifyCommand('docker exec pmm-client-clickhouse pmm-admin add mysql --username=root --password=7B*53@lCdflR --query-source=perfschema mysql5.7 mysql5.7:3306'); + await I.verifyCommand('docker exec pmm-client-clickhouse pmm-admin add mysql --username=root --password=7B*53@lCdflR --query-source=perfschema ps8 ps8:3306'); await I.wait(60); }); From 946f39f2d11d5117ff2e44d8c811408fd52d7aa0 Mon Sep 17 00:00:00 2001 From: yurkovychv Date: Fri, 1 Nov 2024 16:30:06 +0200 Subject: [PATCH 33/33] PMM-7 fix get metric method --- tests/pages/api/grafanaAPI.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/pages/api/grafanaAPI.js b/tests/pages/api/grafanaAPI.js index 2ef75cf30..0e3fa0161 100644 --- a/tests/pages/api/grafanaAPI.js +++ b/tests/pages/api/grafanaAPI.js @@ -366,7 +366,7 @@ module.exports = { datasource: { uid, }, - expr: `${metricName}{${refineBy.type}=\"${refineBy.value}\"}`, + expr: refineBy ? `${metricName}{${refineBy.type}=\"${refineBy.value}\"}` : metricName, }, ], from: 'now-15m', @@ -404,8 +404,8 @@ module.exports = { // Main condition check: metric body is not empty const response = await this.getMetric(metricName, queryBy); - if (response.data.data.result.length !== 0) { - return response; + if (response.data.results.A.frames[0].data.values !== 0) { + return response.data; } // Check the timeout after evaluating main condition