You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2509 lines
62 KiB

<?php
/*
** Zabbix
** Copyright (C) 2001-2023 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/TagTrait.php';
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
/**
* @backup widget, profiles
*
* @onBefore setDefaultWidgetType
*/
class testDashboardGraphWidget extends CWebTest {
use TagTrait;
/**
* Attach MessageBehavior to the test.
*
* @return array
*/
public function getBehaviors() {
return [CMessageBehavior::class];
}
/*
* 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.dashboard_pageid, 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.dashboard.last_widget_type\' AND userid=\'1\'');
DBexecute('INSERT INTO profiles (profileid, userid, idx, value_str, type)'.
' VALUES (99999,1,\'web.dashboard.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=1030');
$dashboard = CDashboardElement::find()->one()->edit();
$overlay = $dashboard->addWidget();
$form = $overlay->asForm();
$element = $overlay->query('id:svg-graph-preview')->one();
$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);
$this->assertScreenshotExcept($overlay, [$element], 'tab_'.$tab);
}
}
/**
* 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=1030');
$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['.CXPathHelper::fromClass('js-remove').']')->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:.//ul[@class='overrides-options-list']//button[".
CXPathHelper::fromClass('js-remove')."]")->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"]')->waitUntilClickable()->one();
if (array_key_exists('error', $data)) {
$this->assertMessage(TEST_BAD, null, $data['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 color field validation.
[
[
'Data set' => [
[
'xpath://button[@id="lbl_ds_0_color"]/..' => ''
]
],
'error' => 'Invalid parameter "Data set/1/color": cannot be empty.'
]
],
[
[
'Data set' => [
[
'xpath://button[@id="lbl_ds_0_color"]/..' => '00000!'
]
],
'error' => 'Invalid parameter "Data set/1/color": a hexadecimal color code (6 symbols) is expected.'
]
],
[
[
'Data set' => [
[
'xpath://button[@id="lbl_ds_0_color"]/..' => '00000 '
]
],
'error' => 'Invalid parameter "Data set/1/color": a hexadecimal color 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',
'xpath://button[@id="lbl_ds_1_color"]/..' => '00000 '
]
],
'error' => 'Invalid parameter "Data set/2/color": a hexadecimal color 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 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 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 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 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 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 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 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' => '2027-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 color field validation.
[
[
'Overrides' => [
[
'options' => [
'Base color'
]
]
],
'error' => 'Invalid parameter "Overrides/1/color": cannot be empty.'
]
],
[
[
'Overrides' => [
[
'color' => '00000!',
'options' => [
'Base color'
]
]
],
'error' => 'Invalid parameter "Overrides/1/color": a hexadecimal color code (6 symbols) is expected.'
]
],
[
[
'Overrides' => [
[
'color' => '00000 ',
'options' => [
'Base color'
]
]
],
'error' => 'Invalid parameter "Overrides/1/color": a hexadecimal color 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 color'
]
]
],
'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',
'Data set label' => '祝你今天過得愉快'
],
[
'host' => ',Zabbix Server',
'item' => ',Agentp ping',
'Draw' => 'Bar',
'Aggregation function' => 'max',
'Data set label' => 'Bar ping'
],
[
'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',
'Draw' => 'Staircase',
'Width' => '10',
'Transparency' => '10',
'Fill' => '10',
'Missing data' => 'Connected',
'Time shift' => '0',
'Aggregation function' => 'last',
'Aggregation interval' => '1',
'Aggregate' => 'Data set',
'xpath://button[@id="lbl_ds_0_color"]/..' => '009688',
'Data set label' => 'Staircase graph'
],
[
'host' => 'Two host',
'item' => 'Two item',
'Y-axis' => 'Right',
'Draw' => 'Points',
'Point size' => '1',
'Transparency' => '0',
'Time shift' => '-1s',
'xpath://button[@id="lbl_ds_1_color"]/..' => '000000'
]
],
'Displaying options' => [
'History data selection' => 'History'
],
'Time period' => [
'Set custom time period' => true,
'From' => '2018-11-15',
'To' => '2018-11-15 14:20:00'
],
'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_*',
'Problem tags' => 'Or'
],
'tags' => [
['name' => 'server', 'value' => 'selenium', 'operator' => 'Equals'],
['name' => 'Street', 'value' => 'dzelzavas']
]
],
'Overrides' => [
[
'host' => 'One host',
'item' => 'One item',
'time_shift' => '-5s',
'color' => '000000',
'options' => [
'Base color',
['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',
'time_shift' => '5s',
'color' => 'FFFFFF',
'options' => [
'Base color',
['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=1030');
$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 values 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',
'Draw' => 'Staircase',
'Width' => '10',
'Transparency' => '10',
'Fill' => '10',
'Missing data' => 'Connected',
'Time shift' => '0',
'xpath://button[@id="lbl_ds_0_color"]/..' => '009688'
],
[
'host' => 'Two host',
'item' => 'Two item',
'Y-axis' => 'Right',
'Draw' => 'Bar',
'Transparency' => '10',
'Transparency' => '0',
'Time shift' => '-1s',
'Aggregation function' => 'avg',
'Aggregation interval' => '5h',
'Aggregate' => 'Data set',
'xpath://button[@id="lbl_ds_1_color"]/..' => '000000'
]
],
'Displaying options' => [
'History data selection' => 'History'
],
'Time period' => [
'Set custom time period' => true,
'From' => '2018-11-15',
'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_*',
'Problem tags' => 'Or'
],
'tags' => [
['name' => 'server', 'value' => 'selenium', 'operator' => 'Equals'],
['name' => 'Street', 'value' => 'dzelzavas']
]
],
'Overrides' => [
[
'host' => 'One host',
'item' => 'One item',
'time_shift' => '-5s',
'color' => '000000',
'options' => [
'Base color',
['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',
'time_shift' => '5s',
'color' => 'FFFFFF',
'options' => [
'Base color',
['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=1030');
$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 values 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=1030');
$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->setTagSelector('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 exists 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
],
'time_shift' => 'name:or['.$i.'][timeshift]',
'color' => [
'selector' => 'xpath://button[@id="lbl_or_'.$i.'__color_"]/..',
'class' => CColorPickerElement::class
]
];
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_"]/..',
'time_shift' => 'name:or['.$i.'][timeshift]',
'color' => 'xpath://button[@id="lbl_or_'.$i.'__color_"]/..'
];
$inputs = [];
foreach ($mapping as $field => $selector) {
if (!array_key_exists($field, $override)) {
continue;
}
$inputs[$selector] = $override[$field];
}
// Check fields value.
$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=1030');
$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=1030');
$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="widget_properties"]')
->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, "dashboard-grid-widget-header")]/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=1030');
$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=1030');
$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=1030');
$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=1030');
$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=1030');
$form = $this->openGraphWidgetConfiguration();
$form->selectTab('Problems');
$fields = ['Selected items only', 'Severity', 'Problem', 'Problem tags', 'Problem hosts'];
$tag_elements = [
'id:evaltype', // Tag type.
'id:tags_0_tag', // Tag name.
'id:tags_0_operator', // 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=1030');
$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 data set naming in legend and in configuration form.
*/
public function testDashboardGraphWidget_CheckDataSetNaming() {
$input_data = [
'main_fields' => [
'Name' => 'Graph widget for Data set naming check'
],
'Data set' => [
[
'host' => 'ЗАББИКС Сервер',
'item' => 'Linux: Available memory*',
'Aggregation function' => 'avg',
'Aggregate' => 'Data set',
'Data set label' => '祝你今天過得愉快'
],
[
'host' => 'ЗАББИКС Сервер',
'item' => 'Linux: CPU guest*',
'Aggregation function' => 'max',
'Data set label' => 'Data set only'
],
[
'host' => 'ЗАББИКС Сервер',
'item' => 'Linux: CPU utilization',
'Aggregation function' => 'count',
'Aggregation interval' => '24h',
'Aggregate' => 'Data set'
]
]
];
$displayed_data = [
'Data sets' => [
'祝你今天過得愉快',
'Data set only',
'Data set #3'
],
'Legend labels' => [
'祝你今天過得愉快', 'max(ЗАББИКС Сервер: Linux: CPU guest nice time)', 'max(ЗАББИКС Сервер: Linux: CPU guest time)',
'Data set #3'
]
];
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid=1030');
$form = $this->openGraphWidgetConfiguration();
// Check hint next to the "Data set label" field.
$form->getLabel('Data set label')->query('xpath:./button[@data-hintbox]')->one()->click();
$hint = $this->query('xpath://div[@class="overlay-dialogue"]')->waitUntilPresent()->one();
$this->assertEquals('Also used as legend label for aggregated data sets.', $hint->getText());
$this->fillForm($input_data, $form);
$form->submit();
$this->saveGraphWidget($input_data['main_fields']['Name']);
// Check labels in legend.
$widget = CDashboardElement::find()->one()->getWidget($input_data['main_fields']['Name']);
$legend_labels = $widget->query('class:svg-graph-legend')->one()->getText();
$this->assertEquals($displayed_data['Legend labels'], explode("\n", $legend_labels));
$form = $widget->edit();
// Check Data set names in created widget configuration form.
$data_set_labels = $form->query('xpath:.//label[@class="sortable-drag-handle js-dataset-label"]')->all()->asText();
$this->assertEquals($displayed_data['Data sets'], array_values($data_set_labels));
}
/**
* 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));
}
}
}