<?php /* ** Zabbix ** Copyright (C) 2001-2022 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ require_once dirname(__FILE__) . '/../../include/CWebTest.php'; require_once dirname(__FILE__).'/../traits/FilterTrait.php'; /** * @backup widget * @backup profiles * * @onBefore setDefaultWidgetType */ class testDashboardGraphWidget extends CWebTest { use FilterTrait; /* * SQL query to get widget and widget_field tables to compare hash values, but without widget_fieldid * because it can change. */ private $sql = 'SELECT wf.widgetid, wf.type, wf.name, wf.value_int, wf.value_str, wf.value_groupid, wf.value_hostid,'. ' wf.value_itemid, wf.value_graphid, wf.value_sysmapid, w.widgetid, w.dashboardid, w.type, w.name, w.x, w.y,'. ' w.width, w.height'. ' FROM widget_field wf'. ' INNER JOIN widget w'. ' ON w.widgetid=wf.widgetid ORDER BY wf.widgetid, wf.name, wf.value_int, wf.value_str, wf.value_groupid,'. ' wf.value_itemid, wf.value_graphid'; /* * Set "Graph" as default widget type. */ public function setDefaultWidgetType() { DBexecute('DELETE FROM profiles WHERE idx=\'web.dashbrd.last_widget_type\' AND userid=\'1\''); DBexecute('INSERT INTO profiles (profileid, userid, idx, value_str, type)'. ' VALUES (99999,1,\'web.dashbrd.last_widget_type\',\'svggraph\',3)'); } /** * Open dashboard and add/edit graph widget. * * @param string $name name of graphic widget to be opened */ private function openGraphWidgetConfiguration($name = null) { $dashboard = CDashboardElement::find()->one()->edit(); // Open existed widget by widget name. if ($name) { $widget = $dashboard->getWidget($name); $this->assertEquals(true, $widget->isEditable()); $form = $widget->edit(); } // Add new graph widget. else { $overlay = $dashboard->addWidget(); $form = $overlay->asForm(); } return $form; } /** * Save dashboard and check added/updated graph widget. * * @param string $name name of graphic widget to be checked */ private function saveGraphWidget($name) { $dashboard = CDashboardElement::find()->one(); $widget = $dashboard->getWidget($name); $widget->query('xpath://div[contains(@class, "is-loading")]')->waitUntilNotPresent(); $widget->getContent()->query('class:svg-graph')->waitUntilVisible(); $dashboard->save(); $message = CMessageElement::find()->waitUntilPresent()->one(); $this->assertTrue($message->isGood()); $this->assertEquals('Dashboard updated', $message->getTitle()); } /* * Check screenshots of graph widget form. * @browsers chrome */ public function testDashboardGraphWidget_FormLayout() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $dashboard = CDashboardElement::find()->one()->edit(); $overlay = $dashboard->addWidget(); $form = $overlay->asForm(); $this->page->removeFocus(); $element = $overlay->query('id:svg-graph-preview')->one(); $errors = []; $tabs = ['Data set', 'Displaying options', 'Time period', 'Axes', 'Legend', 'Problems', 'Overrides']; foreach ($tabs as $tab) { $form->selectTab($tab); if ($tab === 'Overrides') { $button = $form->query('button:Add new override')->one()->click(); // Remove border radius from button element. $this->page->getDriver()->executeScript('arguments[0].style.borderRadius=0;', [$button]); } $this->page->removeFocus(); sleep(1); // Collect all screenshot errors. try { $this->assertScreenshotExcept($overlay, [$element], 'tab_'.$tab); } catch (Exception $ex) { $errors[] = $ex->getMessage(); } } if ($errors) { $this->fail(implode("\n", $errors)); } } /** * Check validation of graph widget fields. */ private function validate($data, $tab) { $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(CTestArrayHelper::get($data, 'Widget name')); $this->fillDatasets(CTestArrayHelper::get($data, 'Data set')); switch ($tab) { case 'Data set': // Remove data set. if (CTestArrayHelper::get($data, 'remove_data_set', false)) { $form->query('xpath://button[@class="remove-btn"]')->one()->click(); } break; case 'Overrides': $form->selectTab($tab); $this->fillOverrides(CTestArrayHelper::get($data, 'Overrides')); // Remove all override options. if (CTestArrayHelper::get($data, 'remove_override_options', false)) { $form->query('xpath://button[@class="subfilter-disable-btn"]')->all()->click(); } break; default: $form->selectTab($tab); $form->fill($data[$tab]); } sleep(2); $form->submit(); COverlayDialogElement::find()->one()->waitUntilReady()->query('xpath:div[@class="overlay-dialogue-footer"]'. '//button[@class="dialogue-widget-save"]')->one()->waitUntilClickable(); if (!is_array($data['error'])) { $data['error'] = [$data['error']]; } // Check error message. $message = $form->getOverlayMessage(); $this->assertTrue($message->isBad()); $count = count($data['error']); $message->query('xpath:./div[@class="msg-details"]/ul/li['.$count.']')->waitUntilPresent(); $this->assertEquals($count, $message->getLines()->count()); foreach ($data['error'] as $error) { $this->assertTrue($message->hasLine($error)); } $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); } public static function getDatasetValidationData() { return [ [ [ 'remove_data_set' => true, 'error' => 'Invalid parameter "Data set": cannot be empty.' ] ], // Base colour field validation. [ [ 'Data set' => [ [ 'Base colour' => '' ] ], 'error' => 'Invalid parameter "Data set/1/color": cannot be empty.' ] ], [ [ 'Data set' => [ [ 'Base colour' => '00000!' ] ], 'error' => 'Invalid parameter "Data set/1/color": a hexadecimal colour code (6 symbols) is expected.' ] ], [ [ 'Data set' => [ [ 'Base colour' => '00000' ] ], 'error' => 'Invalid parameter "Data set/1/color": a hexadecimal colour code (6 symbols) is expected.' ] ], // Time shift field validation. [ [ 'Data set' => [ [ 'Time shift' => 'abc', 'Draw' => 'Points' ] ], 'error' => 'Invalid parameter "Data set/1/timeshift": a time unit is expected.' ] ], [ [ 'Data set' => [ [ 'Time shift' => '5.2' ] ], 'error' => 'Invalid parameter "Data set/1/timeshift": a time unit is expected.' ] ], [ [ 'Data set' => [ [ 'Time shift' => '10000d' ] ], 'error' => 'Invalid parameter "Data set/1/timeshift": value must be one of -788400000-788400000.' ] ], [ [ 'Data set' => [ [ 'Time shift' => '999999999999999999999999999' ] ], 'error' => 'Invalid parameter "Data set/1/timeshift": a number is too large.' ] ], // Aggregation interval validation. [ [ 'Data set' => [ [ 'Aggregation function' => 'min', 'Aggregation interval' => 'abc' ] ], 'error' => 'Invalid parameter "Data set/1/aggregate_interval": a time unit is expected.' ] ], [ [ 'Data set' => [ [ 'Aggregation function' => 'max', 'Aggregation interval' => '5.2' ] ], 'error' => 'Invalid parameter "Data set/1/aggregate_interval": a time unit is expected.' ] ], [ [ 'Data set' => [ [ 'Aggregation function' => 'avg', 'Aggregation interval' => '0' ] ], 'error' => 'Invalid parameter "Data set/1/aggregate_interval": value must be one of 1-788400000.' ] ], [ [ 'Data set' => [ [ 'Aggregation function' => 'count', 'Aggregation interval' => '10000d' ] ], 'error' => 'Invalid parameter "Data set/1/aggregate_interval": value must be one of 1-788400000.' ] ], [ [ 'Data set' => [ [ 'Aggregation function' => 'sum', 'Aggregation interval' => '999999999999999999999999999' ] ], 'error' => 'Invalid parameter "Data set/1/aggregate_interval": a number is too large.' ] ], // Validation of second data set. [ [ 'Data set' => [ [], [ 'Time shift' => '5' ] ], 'error' => 'Invalid parameter "Data set/2/hosts": cannot be empty.' ] ], [ [ 'Data set' => [ [], [ 'item' => 'test', 'Time shift' => '5' ] ], 'error' => 'Invalid parameter "Data set/2/hosts": cannot be empty.' ] ], [ [ 'Data set' => [ [], [ 'host' => 'test' ] ], 'error' => 'Invalid parameter "Data set/2/items": cannot be empty.' ] ], [ [ 'Data set' => [ [], [ 'host' => 'Zabbix*', 'item' => 'Agent ping', 'Base colour' => '00000' ] ], 'error' => 'Invalid parameter "Data set/2/color": a hexadecimal colour code (6 symbols) is expected.' ] ], [ [ 'Data set' => [ [], [ 'host' => '*', 'item' => '*', 'Time shift' => 'abc', 'Draw' => 'Points' ] ], 'error' => 'Invalid parameter "Data set/2/timeshift": a time unit is expected.' ] ], [ [ 'Data set' => [ [], [ 'host' => '*', 'item' => '*', 'Aggregation function' => 'first', 'Aggregation interval' => 'abc' ] ], 'error' => 'Invalid parameter "Data set/2/aggregate_interval": a time unit is expected.' ] ] ]; } /* * Data provider for "Data set" tab validation on creating. */ public function getDatasetValidationCreateData() { $data = []; // Add host and item values for the first "Data set" in each case of the data provider. foreach ($this->getDataSetValidationData() as $item) { if (array_key_exists('Data set', $item[0])) { $item[0]['Data set'][0] = array_merge($item[0]['Data set'][0], [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ]); } $data[] = $item; } // Add additional test cases to data provider. return array_merge($data, [ // Empty host and/or item field. [ [ 'error' => 'Invalid parameter "Data set/1/hosts": cannot be empty.' ] ], [ [ 'Data set' => [ 'item' => '*' ], 'error' => 'Invalid parameter "Data set/1/hosts": cannot be empty.' ] ], [ [ 'Data set' => [ 'host' => '*' ], 'error' => 'Invalid parameter "Data set/1/items": cannot be empty.' ] ] ]); } /* * Data provider for "Data set" tab validation on updating. */ public function getDatasetValidationUpdateData() { $data = []; // Add existing widget name for each case in data provider. foreach ($this->getDataSetValidationData() as $item) { $item[0]['Widget name'] = 'Test cases for update'; $data[] = $item; } // Add additional validation cases. return array_merge($data, [ [ [ 'Widget name' => 'Test cases for update', 'Data set' => [ 'host' => '', 'item' => '' ], 'error' => 'Invalid parameter "Data set/1/hosts": cannot be empty.' ] ], [ [ 'Widget name' => 'Test cases for update', 'Data set' => [ 'host' => '', 'item' => '*' ], 'error' => 'Invalid parameter "Data set/1/hosts": cannot be empty.' ] ], [ [ 'Widget name' => 'Test cases for update', 'Data set' => [ 'host' => '*', 'item' => '' ], 'error' => 'Invalid parameter "Data set/1/items": cannot be empty.' ] ] ]); } /** * Check validation of "Data set" tab. * * @dataProvider getDatasetValidationCreateData * @dataProvider getDatasetValidationUpdateData */ public function testDashboardGraphWidget_DatasetValidation($data) { $this->validate($data, 'Data set'); } public static function getTimePeriodValidationData() { return [ // Empty From/To fields. [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '', 'To' => '' ], 'error' => [ 'Invalid parameter "From": cannot be empty.', 'Invalid parameter "To": cannot be empty.' ] ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-07-04 15:53:07', 'To' => '' ], 'error' => 'Invalid parameter "To": cannot be empty.' ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '', 'To' => '2021-07-04 15:53:07' ], 'error' => [ 'Invalid parameter "From": cannot be empty.', 'Minimum time period to display is 1 minute.' ] ] ], // Date format validation (YYYY-MM-DD HH-MM-SS) [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '1', 'To' => '2021-07-04 15:53:07' ], 'error' => [ 'Invalid parameter "From": a time range is expected.', 'Minimum time period to display is 1 minute.' ] ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-07-04 15:53:07', 'To' => 'abc' ], 'error' => 'Invalid parameter "To": a time range is expected.' ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '5:53:06 2021-07-31', 'To' => '2021-07-04 15:53:07' ], 'error' => [ 'Invalid parameter "From": a time range is expected.', 'Minimum time period to display is 1 minute.' ] ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-02-30 00:00:00', 'To' => '2021-07-04 15:53:07' ], 'error' => [ 'Invalid parameter "From": a time range is expected.', 'Minimum time period to display is 1 minute.' ] ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-05-02 00:00:00', 'To' => '2021-25-09 00:00:00' ], 'error' => 'Invalid parameter "To": a time range is expected.' ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-05-02 00:00:00', 'To' => '2021.07.31 15:53:07' ], 'error' => 'Invalid parameter "To": a time range is expected.' ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-07-04 12:53:00', 'To' => 'now-s' ], 'error' => 'Invalid parameter "To": a time range is expected.' ] ], // Time range validation [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2021-07-04 12:53:00', 'To' => '2021-07-04 12:52:59' ], 'error' => 'Minimum time period to display is 1 minute.' ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => '2022-07-04 12:53:00', 'To' => 'now' ], 'error' => 'Minimum time period to display is 1 minute.' ] ], [ [ 'Time period' => [ 'Set custom time period' => true, 'From' => 'now-58s', 'To' => 'now' ], 'error' => 'Minimum time period to display is 1 minute.' ] ] ]; } public function getTimePeriodValidationCreateData() { $data = []; // Add host and item values for each case in data provider. foreach ($this->getTimePeriodValidationData() as $item) { $item[0]['Data set'] = [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ]; $data[] = $item; } return $data; } public function getTimePeriodValidationUpdateData() { $data = []; foreach ($this->getTimePeriodValidationData() as $item) { $item[0]['Widget name'] = 'Test cases for update'; $data[] = $item; } return $data; } /** * Check validation of "Time period" tab. * * @dataProvider getTimePeriodValidationCreateData * @dataProvider getTimePeriodValidationUpdateData */ public function testDashboardGraphWidget_TimePeriodValidation($data) { $this->validate($data, 'Time period'); } public static function getAxesValidationData() { return [ // Left Y-axis validation. Set by default in first data set. [ [ 'Axes' => [ 'id:lefty_min' => 'abc' ], 'error' => 'Invalid parameter "Left Y/Min": a number is expected.' ] ], [ [ 'Axes' => [ 'id:lefty_max' => 'abc' ], 'error' => 'Invalid parameter "Left Y/Max": a number is expected.' ] ], [ [ 'Axes' => [ 'id:lefty_min' => '10', 'id:lefty_max' => '5' ], 'error' => 'Invalid parameter "Left Y/Max": Y axis MAX value must be greater than Y axis MIN value.' ] ], [ [ 'Axes' => [ 'id:lefty_min' => '-5', 'id:lefty_max' => '-10' ], 'error' => 'Invalid parameter "Left Y/Max": Y axis MAX value must be greater than Y axis MIN value.' ] ], // Change default Y-axis option on Right. [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ] ], 'Axes' => [ 'id:righty_min' => 'abc' ], 'error' => 'Invalid parameter "Right Y/Min": a number is expected.' ] ], [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ] ], 'Axes' => [ 'id:righty_max' => 'abc' ], 'error' => 'Invalid parameter "Right Y/Max": a number is expected.' ] ], [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ] ], 'Axes' => [ 'id:righty_min' => '10', 'id:righty_max' => '5' ], 'error' => 'Invalid parameter "Right Y/Max": Y axis MAX value must be greater than Y axis MIN value.' ] ], [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ] ], 'Axes' => [ 'id:righty_min' => '-5', 'id:righty_max' => '-10' ], 'error' => 'Invalid parameter "Right Y/Max": Y axis MAX value must be greater than Y axis MIN value.' ] ], // Both axes validation. [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ], [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping', 'Y-axis' => 'Left' ] ], 'Axes' => [ 'id:lefty_max' => 'abc', 'id:righty_max' => 'abc' ], 'error' => [ 'Invalid parameter "Left Y/Max": a number is expected.', 'Invalid parameter "Right Y/Max": a number is expected.' ] ] ], [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ], [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping', 'Y-axis' => 'Left' ] ], 'Axes' => [ 'id:lefty_min' => '-5', 'id:lefty_max' => '-10', 'id:righty_min' => '10', 'id:righty_max' => '5' ], 'error' => [ 'Invalid parameter "Left Y/Max": Y axis MAX value must be greater than Y axis MIN value.', 'Invalid parameter "Right Y/Max": Y axis MAX value must be greater than Y axis MIN value.' ] ] ], [ [ 'Data set' => [ [ 'Y-axis' => 'Right' ], [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping', 'Y-axis' => 'Left' ] ], 'Axes' => [ 'id:lefty_min' => 'abc', 'id:lefty_max' => 'def', 'id:righty_min' => '!@#', 'id:righty_max' => '(' ], 'error' => [ 'Invalid parameter "Left Y/Min": a number is expected.', 'Invalid parameter "Left Y/Max": a number is expected.', 'Invalid parameter "Right Y/Min": a number is expected.', 'Invalid parameter "Right Y/Max": a number is expected.' ] ] ] ]; } /* * Add host and item values in data provider. */ public function getAxesValidationCreateData() { $data = []; foreach ($this->getAxesValidationData() as $item) { if (array_key_exists('Data set', $item[0])) { $item[0]['Data set'][0] = array_merge($item[0]['Data set'][0], [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ]); } else { $item[0]['Data set'] = [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ]; } $data[] = $item; } return $data; } public function getAxesValidationUpdateData() { $data = []; foreach ($this->getAxesValidationData() as $item) { $item[0]['Widget name'] = 'Test cases for simple update and deletion'; $data[] = $item; } return $data; } /** * Check "Axes" tab validation. * * @dataProvider getAxesValidationCreateData * @dataProvider getAxesValidationUpdateData */ public function testDashboardGraphWidget_AxesValidation($data) { $this->validate($data, 'Axes'); } public static function getOverridesValidationData() { return [ // Base colour field validation. [ [ 'Overrides' => [ [ 'options' => [ 'Base colour' ] ] ], 'error' => 'Invalid parameter "Overrides/1/color": cannot be empty.' ] ], [ [ 'Overrides' => [ [ 'color' => '00000!', 'options' => [ 'Base colour' ] ] ], 'error' => 'Invalid parameter "Overrides/1/color": a hexadecimal colour code (6 symbols) is expected.' ] ], [ [ 'Overrides' => [ [ 'color' => '00000', 'options' => [ 'Base colour' ] ] ], 'error' => 'Invalid parameter "Overrides/1/color": a hexadecimal colour code (6 symbols) is expected.' ] ], // Time shift field validation. [ [ 'Overrides' => [ [ 'options' => [ 'Time shift' ] ] ], 'error' => 'Invalid parameter "Overrides/1/timeshift": cannot be empty.' ] ], [ [ 'Overrides' => [ [ 'time_shift' => 'abc', 'options' => [ 'Time shift' ] ] ], 'error' => 'Invalid parameter "Overrides/1/timeshift": a time unit is expected.' ] ], [ [ 'Overrides' => [ [ 'time_shift' => '5.2', 'options' => [ 'Time shift' ] ] ], 'error' => 'Invalid parameter "Overrides/1/timeshift": a time unit is expected.' ] ], [ [ 'Overrides' => [ [ 'time_shift' => '10000d', 'options' => [ 'Time shift' ] ] ], 'error' => 'Invalid parameter "Overrides/1/timeshift": value must be one of -788400000-788400000.' ] ], [ [ 'Overrides' => [ [ 'time_shift' => '999999999999999999999999999', 'options' => [ 'Time shift' ] ] ], 'error' => 'Invalid parameter "Overrides/1/timeshift": a number is too large.' ] ], // Validation of second override set. [ [ 'Overrides' => [ [ 'options' => [ ['Width', '5'] ] ], [ 'options' => [ ['Width', '10'] ] ] ], 'error' => 'Invalid parameter "Overrides/2/hosts": cannot be empty.' ] ], [ [ 'Overrides' => [ [ 'options' => [ ['Width', '5'] ] ], [ 'item' => 'Two item', 'options' => [ ['Width', '10'] ] ] ], 'error' => 'Invalid parameter "Overrides/2/hosts": cannot be empty.' ] ], [ [ 'Overrides' => [ [ 'options' => [ ['Width', '5'] ] ], [ 'host' => 'Two host', 'options' => [ ['Width', '10'] ] ] ], 'error' => 'Invalid parameter "Overrides/2/items": cannot be empty.' ] ], [ [ 'Overrides' => [ [ 'options' => [ ['Width', '5'] ] ], [ 'host' => 'Two host', 'item' => 'Two item' ] ], 'error' => 'Invalid parameter "Overrides/2": at least one override option must be specified.' ] ], [ [ 'Overrides' => [ [ 'options' => [ ['Width', '5'] ] ], [ 'host' => 'Two host', 'item' => 'Two item', 'options' => [ 'Base colour' ] ] ], 'error' => 'Invalid parameter "Overrides/2/color": cannot be empty.' ] ], [ [ 'Overrides' => [ [ 'options' => [ ['Width', '5'] ] ], [ 'host' => 'Two host', 'item' => 'Two item', 'time_shift' => 'abc', 'options' => [ 'Time shift' ] ] ], 'error' => 'Invalid parameter "Overrides/2/timeshift": a time unit is expected.' ] ] ]; } /* * Data provider for "Overrides" tab validation on creating. */ public function getOverridesValidationCreateData() { $data = []; // Add host and item values for tab "Data set" and "Overrides" for each data provider. foreach ($this->getOverridesValidationData() as $item) { $item[0]['Data set'] = [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ]; $item[0]['Overrides'][0] = array_merge($item[0]['Overrides'][0], [ 'host' => 'One host', 'item' => 'One item' ]); $data[] = $item; } return array_merge($data, [ [ [ 'Data set' => [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ], 'Overrides' => [ 'item' => '*' ], 'error' => 'Invalid parameter "Overrides/1/hosts": cannot be empty.' ] ], [ [ 'Data set' => [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ], 'Overrides' => [ 'host' => '*' ], 'error' => 'Invalid parameter "Overrides/1/items": cannot be empty.' ] ], [ [ 'Data set' => [ 'host' => 'ЗАББИКС Сервер', 'item' => 'Agent ping' ], 'Overrides' => [ 'host' => '*', 'item' => '*' ], 'error' => 'Invalid parameter "Overrides/1": at least one override option must be specified.' ] ] ]); } /* * Data provider for "Overrides" tab validation on updating. */ public function getOverridesValidationUpdateData() { $data = []; // Add existing widget name for each case in data provider. foreach ($this->getOverridesValidationData() as $item) { $item[0]['Widget name'] = 'Test cases for update'; $data[] = $item; } // Add additional validation cases. return array_merge($data, [ [ [ 'Widget name' => 'Test cases for update', 'remove_override_options' => true, 'error' => 'Invalid parameter "Overrides/1": at least one override option must be specified.' ] ], [ [ 'Widget name' => 'Test cases for update', 'Overrides' => [ 'host' => '', 'item' => '' ], 'error' => 'Invalid parameter "Overrides/1/hosts": cannot be empty.' ] ], [ [ 'Widget name' => 'Test cases for update', 'Overrides' => [ 'host' => '' ], 'error' => 'Invalid parameter "Overrides/1/hosts": cannot be empty.' ] ], [ [ 'Widget name' => 'Test cases for update', 'Overrides' => [ 'item' => '' ], 'error' => 'Invalid parameter "Overrides/1/items": cannot be empty.' ] ] ]); } /** * Check "Overrides" tab validation. * * @dataProvider getOverridesValidationCreateData * @dataProvider getOverridesValidationUpdateData */ public function testDashboardGraphWidget_OverridesValidation($data) { $this->validate($data, 'Overrides'); } public static function getCreateData() { return [ // Mandatory fields only. [ [ 'Data set' => [ 'host' => '*', 'item' => '*' ], 'check_form' => true ] ], // Press button "Add new override", but left override fields empty. [ [ 'Data set' => [ 'host' => 'Add override', 'item' => 'Override empty fields' ], 'Overrides' => [] ] ], // Comma in host and item name. [ [ 'main_fields' => [ 'Name' => 'Comma in host/item names' ], 'Data set' => [ [ 'host' => 'Zabbix,Server', 'item' => 'Agent, Ping', 'Aggregation function' => 'min', 'Aggregate' => 'Data set' ], [ 'host' => ',Zabbix Server', 'item' => ',Agentp ping', 'Draw' => 'Bar', 'Aggregation function' => 'max' ], [ 'host' => ',Zabbix, Server,', 'item' => 'Zabbix configuration cache, % used', 'Aggregation function' => 'count', 'Aggregation interval' => '24h' ] ], 'Overrides' => [ [ 'host' => 'Zabbix,Server', 'item' => 'Agent,Ping', 'options' => [ ['Draw', 'Bar'], ['Missing data', 'Treat as 0'] ] ], [ 'host' => ',Zabbix Server', 'item' => ', Agent ping', 'options' => [ ['Draw', 'Bar'] ] ], [ 'host' => ',,Zabbix Server,,', 'item' => ', Agent, ping,', 'options' => [ ['Draw', 'Bar'] ] ] ], 'check_form' => true ] ], /* Add Width, Fill and Missing data fields in overrides, which are disabled in data set tab. * Fill enabled right Y-axis fields. */ [ [ 'main_fields' => [ 'Name' => 'Test graph widget', 'Refresh interval' => '10 seconds' ], 'Data set' => [ 'host' => ['Zabbix*', 'one', 'two'], 'item' => ['Agent*', 'one', 'two'], 'Draw' => 'Bar', 'Y-axis' => 'Right' ], 'Time period' => [ 'Set custom time period' => true, 'From' => 'now-1w', 'To' => 'now' ], 'Axes' => [ 'id:righty_min' => '-15', 'id:righty_max' => '155.5', 'id:righty_units' => 'Static', 'id:righty_static_units' => 'MB' ], 'Overrides' => [ 'host' => 'One host', 'item' => 'One item', 'options' => [ ['Width', '2'], ['Fill', '2'], ['Missing data', 'None'] ] ], 'check_form' => true ] ], /* Boundary values. * Creation with disabled axes and legend. Enabled Problems, but empty fields in problems tab. */ [ [ 'main_fields' => [ 'Name' => 'Test boundary values', 'Refresh interval' => '10 minutes' ], 'Data set' => [ [ 'host' => '*', 'item' => '*', 'Width' => '0', 'Transparency' => '0', 'Fill' => '0', 'Missing data' => 'Treat as 0', 'Time shift' => '-788400000' ], [ 'host' => 'Two host', 'item' => 'Two item', 'Y-axis' => 'Right', 'Width' => '10', 'Transparency' => '10', 'Fill' => '10', 'Missing data' => 'Connected', 'Time shift' => '788400000', 'Aggregation function' => 'sum', 'Aggregation interval' => '788400000' ] ], 'Displaying options' => [ 'History data selection' => 'Trends' ], 'Time period' => [ 'Set custom time period' => true, 'From' => 'now-59s', 'To' => 'now' ], 'Axes' => [ 'Left Y' => false, 'Right Y' => false, 'X-Axis' => false ], 'Legend' => [ 'Show legend' => false ], 'Problems' => [ 'fields' => [ 'Show problems' => true ] ], 'Overrides' => [ 'host' => 'One host', 'item' => 'One item', 'time_shift' => '788400000', 'options' => [ 'Time shift', ['Draw', 'Staircase'], ['Missing data', 'Treat as 0'] ] ], 'check_form' => true ] ], // All possible fields. [ [ 'main_fields' => [ 'Name' => 'Graph widget with all filled fields', 'Refresh interval' => 'No refresh' ], 'Data set' => [ [ 'host' => 'One host', 'item' => 'One item', 'Base colour' => '009688', 'Draw' => 'Staircase', 'Width' => '10', 'Transparency' => '10', 'Fill' => '10', 'Missing data' => 'Connected', 'Time shift' => '0', 'Aggregation function' => 'last', 'Aggregation interval' => '1', 'Aggregate' => 'Data set' ], [ 'host' => 'Two host', 'item' => 'Two item', 'Base colour' => '000000', 'Y-axis' => 'Right', 'Draw' => 'Points', 'Point size' => '1', 'Transparency' => '0', 'Time shift' => '-1s' ] ], 'Displaying options' => [ 'History data selection' => 'History' ], 'Time period' => [ 'Set custom time period' => true, 'From' => '2018-11-15 08', 'To' => '2018-11-15 14:20' ], 'Axes' => [ 'id:lefty_min' => '5', 'id:lefty_max' => '15.5', 'id:righty_min' => '-15', 'id:righty_max' => '-5', 'id:lefty_units' => 'Static', 'id:lefty_static_units' => 'MB', 'id:righty_units' => 'Static' ], 'Legend' => [ 'Number of rows' => '5' ], 'Problems' => [ 'fields' => [ 'Show problems' => true, 'Selected items only' => false, 'Problem hosts' => ['Simple form test host'], 'Severity' => ['Information', 'Average'], 'Problem' => '2_trigger_*', 'Tags' => 'Or' ], 'tags' => [ ['name' => 'server', 'value' => 'selenium', 'operator' => 'Equals'], ['name' => 'Street', 'value' => 'dzelzavas'] ] ], 'Overrides' => [ [ 'host' => 'One host', 'item' => 'One item', 'color' => '000000', 'time_shift' => '-5s', 'options' => [ 'Base colour', ['Width', '0'], ['Draw', 'Line'], ['Transparency', '0'], ['Fill', '0'], ['Point size', '1'], ['Missing data', 'None'], ['Y-axis', 'Right'], 'Time shift' ] ], [ 'host' => 'Two host', 'item' => 'Two item', 'color' => 'FFFFFF', 'time_shift' => '5s', 'options' => [ 'Base colour', ['Width', '1'], ['Draw', 'Points'], ['Transparency', '2'], ['Fill', '3'], ['Point size', '4'], ['Missing data', 'Connected'], ['Y-axis', 'Left'], 'Time shift' ] ] ], 'check_form' => true ] ] ]; } /** * Check graph widget successful creation. * * @dataProvider getCreateData */ public function testDashboardGraphWidget_Create($data) { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(); $this->fillForm($data, $form); $form->parents('class:overlay-dialogue-body')->one()->query('tag:output')->asMessage()->waitUntilNotVisible(); $form->submit(); $this->saveGraphWidget(CTestArrayHelper::get($data, 'main_fields.Name', 'Graph')); // Check valuse in created widget. if (CTestArrayHelper::get($data, 'check_form', false)) { $this->openGraphWidgetConfiguration(CTestArrayHelper::get($data, 'main_fields.Name', 'Graph')); $this->checkWidgetForm($data); } } public static function getUpdateData() { return [ // Mandatory fields only. [ [ 'Data set' => [ 'host' => 'updated*', 'item' => '*updated' ], 'check_form' => true ] ], /* Add Width, Fill and Missing data fields in overrides, which are disabled in data set tab. * Fill fields for enabled right Y-axis. */ [ [ 'main_fields' => [ 'Refresh interval' => '10 seconds' ], 'Data set' => [ 'host' => ['Zabbix*', 'update', 'two'], 'item' => ['Agent*', 'update', 'two'], 'Draw' => 'Points', 'Y-axis' => 'Right' ], 'Time period' => [ 'Set custom time period' => true, 'From' => 'now-1w', 'To' => 'now' ], 'Axes' => [ 'id:righty_min' => '-15', 'id:righty_max' => '155.5', 'id:righty_units' => 'Static', 'id:righty_static_units' => 'MB' ], 'Overrides' => [ 'host' => 'One host', 'item' => 'One item', 'options' => [ ['Width', '2'], ['Fill', '2'], ['Point size', '5'], ['Missing data', 'None'] ] ], 'check_form' => true ] ], /* Boundary values. * Update with disabled axes and legend. Enabled Problems, but left empty fields in problems tab. */ [ [ 'main_fields' => [ 'Refresh interval' => '10 minutes' ], 'Data set' => [ [ 'host' => '*', 'item' => '*', 'Draw' => 'Line', 'Y-axis' => 'Left', 'Width' => '0', 'Transparency' => '0', 'Fill' => '0', 'Missing data' => 'Treat as 0', 'Time shift' => '-788400000', 'Aggregation function' => 'avg', 'Aggregation interval' => '788400000' ], [ 'host' => 'Two host', 'item' => 'Two item', 'Y-axis' => 'Right', 'Width' => '10', 'Transparency' => '10', 'Fill' => '10', 'Missing data' => 'Connected', 'Time shift' => '788400000' ] ], 'Displaying options' => [ 'History data selection' => 'Trends' ], 'Time period' => [ 'Set custom time period' => true, 'From' => 'now-59s', 'To' => 'now' ], 'Axes' => [ 'Left Y' => false, 'Right Y' => false, 'X-Axis' => false ], 'Legend' => [ 'Show legend' => false ], 'Problems' => [ 'fields' => [ 'Show problems' => true ] ], 'check_form' => true ] ], // Comma in host and item name. [ [ 'Data set' => [ [ 'host' => 'Zabbix,Server', 'item' => 'Agent, Ping', 'Aggregation function' => 'min', 'Aggregate' => 'Data set' ], [ 'host' => ',Zabbix Server', 'item' => ',Agentp ping', 'Draw' => 'Bar', 'Aggregation function' => 'max' ], [ 'host' => ',Zabbix, Server,', 'item' => 'Zabbix configuration cache, % used', 'Aggregation function' => 'count', 'Aggregation interval' => '24h' ] ], 'Overrides' => [ [ 'host' => 'Zabbix,Server', 'item' => 'Agent,Ping', 'options' => [ ['Point size', '5'] ] ], [ 'host' => ',Zabbix Server', 'item' => ', Agent ping', 'options' => [ ['Point size', '5'], ['Draw', 'Bar'] ] ], [ 'host' => ',,Zabbix Server,,', 'item' => ', Agent, ping,', 'options' => [ ['Draw', 'Bar'] ] ] ], 'check_form' => true ] ], // All possible fields. [ [ 'main_fields' => [ 'Name' => 'Update graph widget with all filled fields', 'Refresh interval' => 'No refresh' ], 'Data set' => [ [ 'host' => 'One host', 'item' => 'One item', 'Y-axis' => 'Left', 'Base colour' => '009688', 'Draw' => 'Staircase', 'Width' => '10', 'Transparency' => '10', 'Fill' => '10', 'Missing data' => 'Connected', 'Time shift' => '0' ], [ 'host' => 'Two host', 'item' => 'Two item', 'Base colour' => '000000', 'Y-axis' => 'Right', 'Draw' => 'Bar', 'Transparency' => '10', 'Transparency' => '0', 'Time shift' => '-1s', 'Aggregation function' => 'avg', 'Aggregation interval' => '5h', 'Aggregate' => 'Data set' ] ], 'Displaying options' => [ 'History data selection' => 'History' ], 'Time period' => [ 'Set custom time period' => true, 'From' => '2018-11-15 08', 'To' => '2018-11-15 14:20' ], 'Axes' => [ 'Left Y' => true, 'Right Y' => true, 'X-Axis' => true, 'id:lefty_min' => '5', 'id:lefty_max' => '15.5', 'id:righty_min' => '-15', 'id:righty_max' => '-5', 'id:lefty_units' => 'Static', 'id:lefty_static_units' => 'MB', 'id:righty_units' => 'Static' ], 'Legend' => [ 'Show legend' => true, 'Number of rows' => '5' ], 'Problems' => [ 'fields' => [ 'Show problems' => true, 'Selected items only' => false, 'Problem hosts' => ['Simple form test host', 'ЗАББИКС Сервер'], 'Severity' => ['Information', 'Average'], 'Problem' => '2_trigger_*', 'Tags' => 'Or' ], 'tags' => [ ['name' => 'server', 'value' => 'selenium', 'operator' => 'Equals'], ['name' => 'Street', 'value' => 'dzelzavas'] ] ], 'Overrides' => [ [ 'host' => 'One host', 'item' => 'One item', 'color' => '000000', 'time_shift' => '-5s', 'options' => [ 'Base colour', ['Width', '0'], ['Draw', 'Line'], ['Transparency', '0'], ['Fill', '0'], ['Point size', '1'], ['Missing data', 'None'], ['Y-axis', 'Right'], 'Time shift' ] ], [ 'host' => 'Two host', 'item' => 'Two item', 'color' => 'FFFFFF', 'time_shift' => '5s', 'options' => [ 'Base colour', ['Width', '1'], ['Draw', 'Bar'], ['Transparency', '2'], ['Fill', '3'], ['Point size', '4'], ['Missing data', 'Connected'], ['Y-axis', 'Left'], 'Time shift' ] ] ], 'check_form' => true ] ] ]; } /** * Check graph widget successful update. * * @dataProvider getUpdateData * @backup widget */ public function testDashboardGraphWidget_Update($data) { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration('Test cases for update'); $this->fillForm($data, $form); $form->parents('class:overlay-dialogue-body')->one()->query('tag:output')->asMessage()->waitUntilNotVisible(); $form->submit(); COverlayDialogElement::ensureNotPresent(); $this->saveGraphWidget(CTestArrayHelper::get($data, 'main_fields.Name', 'Test cases for update')); // Check valuse in updated widget. if (CTestArrayHelper::get($data, 'check_form', false)) { $this->openGraphWidgetConfiguration(CTestArrayHelper::get($data, 'main_fields.Name', 'Test cases for update')); $this->checkWidgetForm($data); } } /** * Test update without any modification of graph widget data. */ public function testDashboardGraphWidget_SimpleUpdate() { $name = 'Test cases for simple update and deletion'; $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration($name); $form->submit(); COverlayDialogElement::ensureNotPresent(); $this->saveGraphWidget($name); $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); } /** * Fill graph widget form with provided data. * * @param array $data data provider with fields values * @param array $form CFormElement */ private function fillForm($data, $form) { $form->fill(CTestArrayHelper::get($data, 'main_fields', [])); $this->fillDatasets(CTestArrayHelper::get($data, 'Data set', [])); $tabs = ['Displaying options', 'Time period', 'Axes', 'Legend', 'Problems', 'Overrides']; foreach ($tabs as $tab) { if (!array_key_exists($tab, $data)) { continue; } $form->selectTab($tab); switch ($tab) { case 'Problems': $form->fill(CTestArrayHelper::get($data['Problems'], 'fields', [])); if (array_key_exists('tags', $data['Problems'])) { $this->setFilterSelector('id:tags_table_tags'); $this->setTags($data['Problems']['tags']); } break; case 'Overrides': $this->fillOverrides($data['Overrides']); break; default: $form->fill($data[$tab]); break; } } } /** * Fill "Data sets" with specified data. */ private function fillDatasets($data_sets) { $form = $this->query('id:widget_dialogue_form')->asForm()->one(); if ($data_sets) { if (CTestArrayHelper::isAssociative($data_sets)) { $data_sets = [$data_sets]; } $last = count($data_sets) - 1; // Amount of data sets on frontend. $count_sets = $form->query('xpath://li[contains(@class, "list-accordion-item")]')->all()->count(); foreach ($data_sets as $i => $data_set) { $mapping = [ 'host' => 'xpath://div[@id="ds_'.$i.'_hosts_"]/..', 'item' => 'xpath://div[@id="ds_'.$i.'_items_"]/..' ]; // If host or item of data set exist in data provider, add the xpath selector and value from data provider to them. foreach ($mapping as $field => $selector) { if (array_key_exists($field, $data_set)) { $data_set = [$selector => $data_set[$field]] + $data_set; unset($data_set[$field]); } } $form->fill($data_set); // Open next dataset, if it exist on frontend. if ($i !== $last) { if ($i + 1 < $count_sets) { $i += 2; $form->query('xpath:(//li[contains(@class, "list-accordion-item")])['.$i.']//button')->one()->click(); } // Press "Add new data set" button, except for last data set. else { $form->query('button:Add new data set')->one()->click(); } $form->invalidate(); } } } } /** * Fill "Overrides" with specified data. */ private function fillOverrides($overrides) { $form = $this->query('id:widget_dialogue_form')->asForm()->one(); // Check if override already exist in list, if not, add new override. $items = $form->query('class:overrides-list-item')->all(); if ($items->count() === 0) { $form->query('button:Add new override')->one()->click(); } if ($overrides) { if (CTestArrayHelper::isAssociative($overrides)) { $overrides = [$overrides]; } $last = count($overrides) - 1; foreach ($overrides as $i => $override) { // Prepare non-standard fields. $mapping = [ 'options' => [ 'selector' => 'xpath://button[@data-row='.CXPathHelper::escapeQuotes($i).']', 'class' => CPopupButtonElement::class ], 'host' => [ 'selector' => 'xpath://div[@id="or_'.$i.'_hosts_"]/..', 'class' => CMultiselectElement::class ], 'item' => [ 'selector' => 'xpath://div[@id="or_'.$i.'_items_"]/..', 'class' => CMultiselectElement::class ], 'color' => 'id:or_'.$i.'__color_', 'time_shift' => 'name:or['.$i.'][timeshift]' ]; foreach ($mapping as $field => $item) { if (!array_key_exists($field, $override)) { continue; } if (!is_array($item)) { $item = ['selector' => $item, 'class' => CElement::class]; } $form->query($item['selector'])->cast($item['class'])->one()->fill($override[$field]); } // Press "Add new override" button, except for last override set and if in data provider exist only one set. if ($i !== $last) { $form->query('button:Add new override')->one()->click(); } } } } /** * Check widget field values after creating or updating. */ private function checkWidgetForm($data) { $form = $this->query('id:widget_dialogue_form')->asForm()->one(); // Check values in "Data set" tab. if (CTestArrayHelper::isAssociative($data['Data set'])) { $data['Data set'] = [$data['Data set']]; } $last = count($data['Data set']) - 1; foreach ($data['Data set'] as $i => $data_set) { // Prepare host and item fields. $mapping = [ 'host' => 'xpath://div[@id="ds_'.$i.'_hosts_"]/..', 'item' => 'xpath://div[@id="ds_'.$i.'_items_"]/..' ]; foreach ($mapping as $field => $selector) { $data_set = [$selector => $data_set[$field]] + $data_set; unset($data_set[$field]); } // Check fields value. $form->checkValue($data_set); // Open next data set, if exist. if ($i !== $last) { $i += 2; $form->query('xpath:(//li[contains(@class, "list-accordion-item")])['.$i.']//button')->one()->click(); $form->invalidate(); } } // Check values in 'Displaying options', 'Time period', 'Axes' and 'Legend' tabs $tabs = ['Displaying options', 'Time period', 'Axes', 'Legend']; foreach ($tabs as $tab) { if (array_key_exists($tab, $data)) { $form->selectTab($tab); $form->checkValue($data[$tab]); } } // Check values in Problems tab. if (array_key_exists('Problems', $data)) { $form->selectTab('Problems'); $form->checkValue(CTestArrayHelper::get($data, 'Problems.fields', [])); if (array_key_exists('tags', $data['Problems'])) { $this->assertTags($data['Problems']['tags'], 'id:tags_table_tags'); } } // Check values in Overrides tab. if (array_key_exists('Overrides', $data)) { $form->selectTab('Overrides'); if (CTestArrayHelper::isAssociative($data['Overrides'])) { $data['Overrides'] = [$data['Overrides']]; } foreach ($data['Overrides'] as $i => $override) { // Prepare input fields. $mapping = [ 'host' => 'xpath://div[@id="or_'.$i.'_hosts_"]/..', 'item' => 'xpath://div[@id="or_'.$i.'_items_"]/..', 'color' => 'id:or_'.$i.'__color_', 'time_shift' => 'name:or['.$i.'][timeshift]' ]; $inputs = []; foreach ($mapping as $field => $selector) { if (!array_key_exists($field, $override)) { continue; } $inputs[$selector] = $override[$field]; } $form->checkValue($inputs); // Check values of override options in data provider and in widget, except color and time shift fields. if (array_key_exists('options', $override)) { $i++; $list = $this->query('xpath:(//ul[@class="overrides-options-list"])['.$i.']')->one(); $options = $list->query('xpath:.//span[@data-option]')->all(); $options_text = $options->asText(); // Check number of override options in data provider and in widget. $values = array_filter($override['options'], function ($option) { return (is_array($option) && count($option) === 2); }); $this->assertEquals(count($values), $options->count()); foreach ($override['options'] as $option) { if (is_array($option) && count($option) === 2) { $this->assertContains(implode(': ', $option), $options_text); } } } } } } public static function getDashboardCancelData() { return [ // Add new graph widget. [ [ 'main_fields' => [ 'Name' => 'Add new graph widget and cancel dashboard update' ], 'Data set' => [ 'host' => 'Zabbix*, new widget', 'item' => 'Agetn*, new widget' ] ] ], // Update existing graph widget. [ [ 'Existing widget' => 'Test cases for simple update and deletion', 'main_fields' => [ 'Name' => 'Update graph widget and cancel dashboard' ], 'Data set' => [ 'host' => 'Update widget, cancel dashboard update', 'item' => 'Update widget' ] ] ] ]; } /** * Update existing widget or create new and cancel dashboard update. * * @dataProvider getDashboardCancelData */ public function testDashboardGraphWidget_cancelDashboardUpdate($data) { $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(CTestArrayHelper::get($data, 'Existing widget', [])); $form->fill(CTestArrayHelper::get($data, 'main_fields', [])); $this->fillDataSets($data['Data set']); $form->submit(); // Check added or updated graph widget. $dashboard = CDashboardElement::find()->one(); $widget = $dashboard->getWidget(CTestArrayHelper::get($data, 'main_fields.Name', 'Graph')); $widget->getContent()->query('class:svg-graph')->waitUntilVisible(); $dashboard->cancelEditing(); $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); } public static function getWidgetCancelData() { return [ // Add new graph widget. [ [ 'main_fields' => [ 'Name' => 'Cancel widget create' ], 'Data set' => [ 'host' => 'Cancel create', 'item' => 'Cancel create' ] ] ], // Update existing graph widget. [ [ 'Existing widget' => 'Test cases for simple update and deletion', 'main_fields' => [ 'Name' => 'Cancel widget update' ], 'Data set' => [ 'host' => 'Cancel update', 'item' => 'Cancel update' ] ] ] ]; } /** * Cancel update of existing widget or cancel new widget creation and save dashboard. * * @dataProvider getDashboardCancelData */ public function testDashboardGraphWidget_cancelWidgetEditing($data) { $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(CTestArrayHelper::get($data, 'Existing widget', [])); $form->fill($data['main_fields']); $this->fillDataSets($data['Data set']); $overlay = $this->query('xpath://div[contains(@class, "overlay-dialogue")][@data-dialogueid="widgetConfg"]') ->asOverlayDialog()->one(); $overlay->close(); // Check canceled graph widget. $dashboard = CDashboardElement::find()->one(); // If test fails and widget isn't canceled, need to wait until widget appears on the dashboard. sleep(2); $this->assertTrue(!$dashboard->query('xpath:.//div[contains(@class, "dashbrd-grid-widget-head")]/h4[text()='. CXPathHelper::escapeQuotes($data['main_fields']['Name']).']')->one(false)->isValid()); $dashboard->save(); $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); } /** * Test deleting of graph widget. */ public function testDashboardGraphWidget_Delete() { $name = 'Test cases for simple update and deletion'; $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $dashboard = CDashboardElement::find()->one(); $widget = $dashboard->edit()->getWidget($name); $this->assertEquals(true, $widget->isEditable()); $dashboard->deleteWidget($name); $dashboard->save(); $this->page->waitUntilReady(); $message = CMessageElement::find()->waitUntilPresent()->one(); $this->assertTrue($message->isGood()); $this->assertEquals('Dashboard updated', $message->getTitle()); // Check that widget is not present on dashboard and in DB. $this->assertTrue(!$dashboard->getWidget($name, false)->isValid()); $sql = 'SELECT * FROM widget_field wf LEFT JOIN widget w ON w.widgetid=wf.widgetid'. ' WHERE w.name='.zbx_dbstr($name); $this->assertEquals(0, CDBHelper::getCount($sql)); } /** * Test disabled fields in "Data set" tab. */ public function testDashboardGraphWidget_DatasetDisabledFields() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(); foreach (['Line', 'Points', 'Staircase', 'Bar'] as $option) { $form->fill(['Draw' => $option]); // Check the disabled fields depending on selected Draw option. switch ($option) { case 'Line': case 'Staircase': $fields = ['Point size']; break; case 'Points': $fields = ['Width', 'Fill', 'Missing data']; break; case 'Bar': $fields = ['Width', 'Fill', 'Point size', 'Missing data']; break; } $this->assertEnabledFields($fields, false); } $fields = ['Aggregation interval', 'Aggregate']; $this->assertEnabledFields($fields, false); $form->fill(['Aggregation function' => 'min']); $this->assertEnabledFields($fields, true); } /* * Test "From" and "To" fields in tab "Time period" by check/uncheck "Set custom time period". */ public function testDashboardGraphWidget_TimePeriodDisabledFields() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(); $form->selectTab('Time period'); $fields = ['From', 'To']; $this->assertEnabledFields($fields, false); $form->fill(['Set custom time period' => true]); $this->assertEnabledFields($fields, true); } /* * Test enable/disable "Number of rows" field by check/uncheck "Show legend". */ public function testDashboardGraphWidget_LegendDisabledFields() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(); $form->selectTab('Legend'); $this->assertEnabledFields('Number of rows'); $form->fill(['Show legend' => false]); $this->assertEnabledFields('Number of rows', false); } public function testDashboardGraphWidget_ProblemsDisabledFields() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(); $form->selectTab('Problems'); $fields = ['Selected items only', 'Severity', 'Problem', 'Tags', 'Problem hosts']; $tag_elements = [ 'id:evaltype', // Tag type. 'id:tags_0_tag', // Tag name. 'id:tags_0_operator_0', // Tag operator. 'id:tags_0_value', // Tag value 'id:tags_0_remove', // Tag remove button. 'id:tags_add' // Tagg add button. ]; $this->assertEnabledFields(array_merge($fields, $tag_elements), false); // Set "Show problems" and check that fields enabled now. $form->fill(['Show problems' => true]); $this->assertEnabledFields(array_merge($fields, $tag_elements), true); } public static function getAxesDisabledFieldsData() { return [ [ [ 'Data set' => [ 'Y-axis' => 'Right' ] ] ], [ [ 'Data set' => [ 'Y-axis' => 'Left' ] ] ], // Both Y-axis are enabled, if in data set selected Left axis, but in Overrides selected Right. [ [ 'Data set' => [ 'Y-axis' => 'Right' ], 'Overrides' => [ 'options' => [ ['Y-axis', 'Left'] ] ] ] ], [ [ 'Data set' => [ 'Y-axis' => 'Left' ], 'Overrides' => [ 'options' => [ ['Y-axis', 'Right'] ] ] ] ] ]; } /** * Check that the axes fields are disabled depending on the selected axis in Data set and in Overrides. * * @dataProvider getAxesDisabledFieldsData */ public function testDashboardGraphWidget_AxesDisabledFields($data) { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=103'); $form = $this->openGraphWidgetConfiguration(); $form->fill($data['Data set']); $axis = $data['Data set']['Y-axis']; if (array_key_exists('Overrides', $data)) { $axis = 'Both'; $form->selectTab('Overrides'); $this->fillOverrides($data['Overrides']); } $form->selectTab('Axes'); $lefty_fields = ['id:lefty', 'id:lefty_min', 'id:lefty_max', 'id:lefty_units']; $righty_fields = ['id:righty', 'id:righty_min', 'id:righty_max', 'id:righty_units']; switch ($axis) { case 'Right': $lefty_fields[] = 'id:lefty_static_units'; $this->assertEnabledFields($lefty_fields, false); $this->assertEnabledFields($righty_fields, true); $this->assertFalse($this->query('id:righty_static_units')->one()->isEnabled()); break; case 'Left': $righty_fields[] = 'id:righty_static_units'; $this->assertEnabledFields($lefty_fields, true); $this->assertEnabledFields($righty_fields, false); $this->assertFalse($this->query('id:lefty_static_units')->one()->isEnabled()); break; case 'Both'; $this->assertEnabledFields($lefty_fields, true); $this->assertEnabledFields($righty_fields, true); $this->assertFalse($this->query('id:righty_static_units')->one()->isEnabled()); $this->assertFalse($this->query('id:lefty_static_units')->one()->isEnabled()); break; } } /** * Check that fields are enabled or disabled. * * @param array $fields array of checked fields * @param boolean $enabled fields state are enabled * @param boolean $id is used field id instead of field name */ private function assertEnabledFields($fields, $enabled = true) { $form = $this->query('id:widget_dialogue_form')->asForm()->one(); if (!is_array($fields)) { $fields = [$fields]; } foreach ($fields as $field) { $this->assertTrue($form->getField($field)->isEnabled($enabled)); } } }