.
**/
require_once dirname(__FILE__).'/../../include/CWebTest.php';
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
require_once dirname(__FILE__).'/../behaviors/CTableBehavior.php';
require_once dirname(__FILE__).'/../common/testWidgets.php';
/**
* @backup dashboard
*
* @onBefore prepareData
*
* @dataSource AllItemValueTypes
*/
class testDashboardItemHistoryWidget extends testWidgets {
/**
* Attach MessageBehavior and TableBehavior to the test.
*
* @return array
*/
public function getBehaviors() {
return [
CMessageBehavior::class,
CTableBehavior::class
];
}
const DEFAULT_WIDGET = 'Default Item history Widget';
const DELETE_WIDGET = 'Widget for delete';
const DATA_WIDGET = 'Widget for data check';
protected static $dashboardid;
protected static $dashboard_create;
protected static $dashboard_data;
protected static $update_widget = 'Update Item history Widget';
public static function prepareData() {
// Create host for widget header and data tests.
CDataHelper::createHosts([
[
'host' => 'Simple host with item for Item history widget',
'interfaces' => [
[
'type' => INTERFACE_TYPE_AGENT,
'main' => INTERFACE_PRIMARY,
'useip' => INTERFACE_USE_IP,
'ip' => '127.0.9.1',
'dns' => '',
'port' => '10077'
]
],
'groups' => [
'groupid' => '4'
],
'items' => [
[
'name' => 'Test Item history',
'key_' => 'plain_text',
'type' => ITEM_TYPE_ZABBIX,
'value_type' => ITEM_VALUE_TYPE_FLOAT,
'delay' => '30'
]
]
]
]);
$itemids = CDataHelper::getIds('name');
$response = CDataHelper::call('dashboard.create', [
[
'name' => 'Dashboard for Item history Widget test',
'pages' => [
[
'name' => 'Page with default widgets',
'widgets' => [
[
'type' => 'itemhistory',
'name' => self::DEFAULT_WIDGET,
'x' => 0,
'y' => 0,
'width' => 12,
'height' => 5,
'fields' => [
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.0.name',
'value' => 'Column_1'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.0.itemid',
'value' => '42227' // item name in widget 'ЗАББИКС Сервер: Linux: Host name of Zabbix agent running'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'override_hostid._reference',
'value' => 'DASHBOARD._hostid'
]
]
],
[
'type' => 'itemhistory',
'name' => self::DELETE_WIDGET,
'x' => 0,
'y' => 5,
'width' => 12,
'height' => 5,
'fields' => [
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.0.name',
'value' => 'Column_1'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.0.itemid',
'value' => '42227' // item name in widget 'ЗАББИКС Сервер: Linux: Host name of Zabbix agent running'.
]
]
]
]
]
]
],
[
'name' => 'Dashboard for Item history Widget create/update test',
'pages' => [
[
'name' => 'Page with created/updated widgets',
'widgets' => [
[
'type' => 'itemhistory',
'name' => self::$update_widget,
'x' => 0,
'y' => 0,
'width' => 12,
'height' => 5,
'fields' => [
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.0.name',
'value' => 'Update column 1'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.0.itemid',
'value' => '42243' // item name in widget 'ЗАББИКС Сервер: Available memory'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'reference',
'value' => 'EDCBA'
]
]
],
[
'type' => 'graph',
'name' => 'Classic graph for time period reference',
'x' => 12,
'y' => 0,
'width' => 24,
'height' => 5,
'fields' => [
[
'type' => ZBX_WIDGET_FIELD_TYPE_INT32,
'name' => 'source_type',
'value' => 1
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'itemid.0',
'value' => $itemids['Test Item history']
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'reference',
'value' => 'FEDCB'
]
]
]
]
]
]
],
[
'name' => 'Dashboard for checking data',
'pages' => [
[
'name' => 'Page with Item history widget',
'widgets' => [
[
'type' => 'itemhistory',
'name' => self::DATA_WIDGET,
'x' => 0,
'y' => 0,
'width' => 60,
'height' => 6,
'fields' => [
[
'type' => ZBX_WIDGET_FIELD_TYPE_INT32,
'name' => 'show_timestamp',
'value' => 1
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'time_period.from',
'value' => 'now-1y'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'time_period.to',
'value' => 'now/d'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.0.name',
'value' => 'Host name'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.0.itemid',
'value' => '42227' // item name in widget 'ЗАББИКС Сервер: Linux: Host name of Zabbix agent running'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.1.name',
'value' => 'Available memory'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_INT32,
'name' => 'columns.1.history',
'value' => 1
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.1.itemid',
'value' => '42243' // item name in widget 'ЗАББИКС Сервер: Linux: Available memory'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.2.name',
'value' => 'Available memory in %'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_INT32,
'name' => 'columns.2.history',
'value' => 1
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.2.itemid',
'value' => '42244' // item name in widget 'ЗАББИКС Сервер: Linux: Available memory in %'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.3.name',
'value' => 'Test Item history'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.3.itemid',
'value' => $itemids['Test Item history'] // item name in widget 'Simple host with item for Item history widget: Test Item history'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_INT32,
'name' => 'columns.3.history',
'value' => 1
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'columns.4.name',
'value' => 'Master item'
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_INT32,
'name' => 'columns.4.history',
'value' => 1
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_ITEM,
'name' => 'columns.4.itemid',
'value' => '99142' // item name in widget 'Test item host: Master item'.
],
[
'type' => ZBX_WIDGET_FIELD_TYPE_STR,
'name' => 'override_hostid._reference',
'value' => 'DASHBOARD._hostid'
]
]
]
]
]
]
]
]);
self::$dashboardid = $response['dashboardids'][0];
self::$dashboard_create = $response['dashboardids'][1];
self::$dashboard_data = $response['dashboardids'][2];
}
public function testDashboardItemHistoryWidget_Layout() {
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid)->waitUntilReady();
$dashboard = CDashboardElement::find()->one();
$dialog = $dashboard->edit()->addWidget();
$this->assertEquals('Add widget', $dialog->getTitle());
$form = $dialog->asForm();
$form->fill(['Type' => CFormElement::RELOADABLE_FILL('Item history')]);
// Check default state.
$default_state = [
'Type' => 'Item history',
'Name' => '',
'Show header' => true,
'Refresh interval' => 'Default (1 minute)',
'Columns' => [],
'Show lines' => '25',
'Override host' => '',
'New values' => 'Top',
'Show timestamp' => false,
'Show column header' => 'Vertical',
'Time period' => 'Dashboard',
'Widget' => '',
'id:time_period_from' => 'now-1h',
'id:time_period_to' => 'now'
];
$form->checkValue($default_state);
// Check required fields.
$this->assertEquals(['Columns', 'Show lines'], $form->getRequiredLabels());
// Check attributes of input elements.
$inputs = [
'Name' => [
'maxlength' => '255',
'placeholder' => 'default'
],
'Show lines' => [
'maxlength' => '3'
],
'id:override_hostid_ms' => [
'placeholder' => 'type here to search'
],
'id:time_period_from' => [
'maxlength' => '255',
'placeholder' => 'YYYY-MM-DD hh:mm:ss'
],
'id:time_period_to' => [
'maxlength' => '255',
'placeholder' => 'YYYY-MM-DD hh:mm:ss'
]
];
foreach ($inputs as $field => $attributes) {
$this->assertTrue($form->getField($field)->isAttributePresent($attributes));
}
// Check radio buttons.
$radiobuttons = [
'Layout' => ['Horizontal', 'Vertical'],
'New values' => ['Top', 'Bottom'],
'Show column header' => ['Off', 'Horizontal', 'Vertical'],
'Time period' => ['Dashboard', 'Widget', 'Custom']
];
foreach ($radiobuttons as $field => $labels) {
$this->assertEquals($labels, $form->getField($field)->getLabels()->asText());
}
$refresh_interval = ['Default (1 minute)', 'No refresh', '10 seconds', '30 seconds', '1 minute',
'2 minutes', '10 minutes', '15 minutes'
];
$this->assertEquals($refresh_interval, $form->getField('Refresh interval')->getOptions()->asText());
// Check Column popup.
$form->getFieldContainer('Columns')->query('button:Add')->waitUntilClickable()->one()->click();
$column_overlay = COverlayDialogElement::find()->all()->last()->waitUntilReady();
$this->assertEquals('New column', $column_overlay->getTitle());
$column_form = $column_overlay->asForm();
$this->assertEquals(['Name', 'Item', 'Base colour', 'Highlights', 'Display', 'Min', 'Max', 'Thresholds',
'History data', 'Use monospace font', 'Display local time', 'Show thumbnail'],
$column_form->getLabels()->asText()
);
$this->assertEquals(['Name', 'Item'], $column_form->getRequiredLabels());
$defaults = [
'Name' => ['value' => '', 'maxlength' => 255],
'Item' => ['value' => ''],
'xpath://input[@id="base_color"]/..' => ['value' => ''],
'Display' => ['value' => 'As is', 'lables' => ['As is', 'HTML', 'Single line']],
'Min' => ['value' => '', 'placeholder' => 'calculated', 'maxlength' => 255],
'Max' => ['value' => '', 'placeholder' => 'calculated', 'maxlength' => 255],
'History data' => ['value' => 'Auto', 'lables' => ['Auto', 'History', 'Trends']],
'id:max_length' => ['value' => 100, 'maxlength' => 3],
'Use monospace font' => ['value' => false],
'Display local time' => ['value' => false],
'Show thumbnail' => ['value' => false]
];
foreach ($defaults as $label => $attributes) {
$field = $column_form->getField($label);
$this->assertEquals($attributes['value'], $field->getValue());
foreach (['maxlength', 'placeholder'] as $attribute) {
if (array_key_exists($attribute, $attributes)) {
$this->assertEquals($attributes[$attribute], $field->getAttribute($attribute));
}
}
if (array_key_exists('labels', $attributes)) {
$this->assertEquals($attributes['labels'], $field->asSegmentedRadio()->getLabels()->asText());
}
}
// Check buttons in column dialog.
$this->assertEquals(['Add', 'Cancel'], $column_overlay->getFooter()->query('button')->all()
->filter(CElementFilter::CLICKABLE)->asText()
);
// Check initial visible fields.
foreach (['Name', 'Item', 'Base colour'] as $label) {
$field = $column_form->getField($label);
$this->assertTrue($field->isEnabled());
$this->assertTrue($field->isVisible());
}
// Check fields for binary item.
$column_form->fill(['Item' => 'Binary item']);
// Check that name is filled automatically.
$this->assertEquals('Host for all item value types: Binary item', $column_form->getField('Name')->getValue());
$this->assertEquals(['Name', 'Item', 'Base colour', 'Show thumbnail'],
array_values($column_form->getLabels()->filter(CElementFilter::VISIBLE)->asText())
);
// Check fields for character, text and log items.
foreach (['Character item', 'Text item', 'Log item'] as $i => $item) {
$column_form->fill(['Item' => $item]);
$this->assertEquals('Host for all item value types: '.$item, $column_form->getField('Name')->getValue());
$labels = ($item === 'Log item')
? ['Name', 'Item', 'Base colour', 'Highlights', 'Display', 'Use monospace font', 'Display local time']
: ['Name', 'Item', 'Base colour', 'Highlights', 'Display', 'Use monospace font'];
$this->assertEquals($labels, array_values($column_form->getLabels()->filter(CElementFilter::VISIBLE)->asText()));
$this->checkThresholdsHighlights($column_form, 'Highlights', $i, '_pattern');
$this->checkHint($column_form, 'Display',
'Single line - result will be displayed in a single line and truncated to specified length.'
);
$display_maxlength_dependencies = [
'As is' => false,
'HTML' => false,
'Single line' => true
];
foreach ($display_maxlength_dependencies as $label => $status) {
$column_form->fill(['Display' => $label]);
$max_length = $column_form->getField('id:max_length');
$this->assertTrue($max_length->isEnabled($status));
$this->assertTrue($max_length->isVisible($status));
}
if ($item === 'Log item') {
$this->checkHint($column_form, 'Display local time', 'This setting will display local time'.
' instead of the timestamp. "Show timestamp" must also be checked in the advanced configuration.'
);
}
}
// Check fields for float and unsigned item.
foreach (['Float item', 'Unsigned item'] as $j => $item) {
$column_form->fill(['Item' => $item]);
$this->assertEquals(['Name', 'Item', 'Base colour', 'Display', 'Thresholds', 'History data'],
array_values($column_form->getLabels()->filter(CElementFilter::VISIBLE)->asText())
);
$display_fields = [
'Bar' => true,
'Indicators' => true,
'As is' => false
];
foreach ($display_fields as $label => $status) {
$column_form->fill(['Display' => $label]);
foreach (['Min', 'Max'] as $display_input) {
$input = $column_form->getField($display_input);
$this->assertTrue($input->isEnabled($status));
$this->assertTrue($input->isVisible($status));
}
}
$this->checkThresholdsHighlights($column_form, 'Thresholds', $j, '_threshold');
}
$column_overlay->close();
// Check if buttons present and clickable.
$this->assertEquals(['Add', 'Cancel'], $dialog->getFooter()->query('button')->all()
->filter(CElementFilter::CLICKABLE)->asText()
);
$visible_labels = ['Type', 'Show header', 'Name', 'Refresh interval', 'Layout', 'Columns', 'Show lines',
'Override host', 'Advanced configuration'
];
$hidden_labels = ['New values', 'Show timestamp', 'Show column header', 'Time period', 'Widget', 'From', 'To'];
$this->assertEquals($visible_labels, array_values($form->getLabels()->filter(CElementFilter::VISIBLE)->asText()));
$this->assertEquals($hidden_labels, array_values($form->getLabels()->filter(CElementFilter::NOT_VISIBLE)->asText()));
$expanded_labels = ['New values', 'Show timestamp', 'Show column header', 'Time period'];
$form->fill(['Advanced configuration' => true]);
$this->assertEquals(array_merge($visible_labels, $expanded_labels),
array_values($form->getLabels()->filter(CElementFilter::VISIBLE)->asText())
);
$time_period_fields = [
'Dashboard' => ['Widget' => false, 'From' => false, 'To' => false],
'Widget' => ['Widget' => true, 'From' => false, 'To' => false],
'Custom' => ['Widget' => false, 'From' => true, 'To' => true]
];
foreach ($time_period_fields as $label => $visibility) {
$form->fill(['Time period' => $label]);
foreach ($visibility as $field => $status) {
$this->assertTrue($form->getField($field)->isEnabled($status));
}
// Check Widget multiselect's placeholder.
if ($label === 'Widget') {
$this->assertTrue($form->getField('id:time_period_reference_ms')
->isAttributePresent(['placeholder' => 'type here to search'])
);
}
// Check calendar buttons.
if ($label === 'Custom') {
foreach (['time_period_from_calendar', 'time_period_to_calendar'] as $button) {
$this->assertTrue($form->query('id', $button)->one()->isClickable());
}
}
}
$dialog->close();
$dashboard->save();
// Check parameter 'Override host' true/false state.
$host_selector = $dashboard->getControls()->query('class:multiselect-control')->asMultiselect()->one();
$this->assertTrue($host_selector->isVisible());
$dashboard->getWidget(self::DEFAULT_WIDGET)->edit();
$this->assertEquals('Edit widget', $dialog->getTitle());
$form->fill(['Override host' => ''])->submit();
$dashboard->save();
$this->assertFalse($host_selector->isVisible());
}
public static function getWidgetData() {
return [
// #0.
[
[
'expected' => TEST_BAD,
'error' => 'Invalid parameter "Columns": cannot be empty.'
]
],
// #1.
[
[
'expected' => TEST_BAD,
'fields' => [
'Show lines' => ''
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
],
'error' => ['Invalid parameter "Show lines": value must be one of 1-100.']
]
],
// #2.
[
[
'expected' => TEST_BAD,
'fields' => [
'Show lines' => '0'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
],
'error' => 'Invalid parameter "Show lines": value must be one of 1-100.'
]
],
// #3.
[
[
'expected' => TEST_BAD,
'fields' => [
'Show lines' => '101'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
],
'error' => 'Invalid parameter "Show lines": value must be one of 1-100.'
]
],
// #4.
[
[
'expected' => TEST_BAD,
'fields' => [
'Show lines' => ' '
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
],
'error' => 'Invalid parameter "Show lines": value must be one of 1-100.'
]
],
// #5.
[
[
'expected' => TEST_BAD,
'fields' => [
'Show lines' => ''
],
'error' => [
'Invalid parameter "Columns": cannot be empty.',
'Invalid parameter "Show lines": value must be one of 1-100.'
]
]
],
// #6.
[
[
'expected' => TEST_GOOD,
'same_host' => 'ЗАББИКС Сервер',
'fields' => [
'Name' => '2 columns from one host'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
],
[
'fields' => [
'Name' => 'Column2',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #7 Test case with items from two different hosts.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => ''
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
],
[
'fields' => [
'Name' => 'Column2',
'Item' => [
'values' => 'Test Item history',
'context' => ['values' => 'Simple host with item for Item history widget']
]
]
]
]
]
],
// #8 Test case with items from the same host and with custom name.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Test custom name'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
],
[
'fields' => [
'Name' => 'Column2',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #9 Test case with items from two different hosts and with custom name.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Test custom name2'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory in %',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
],
[
'fields' => [
'Name' => 'Column2',
'Item' => [
'values' => 'Test Item history',
'context' => ['values' => 'Simple host with item for Item history widget']
]
]
]
]
]
],
// #10.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Custom refresh',
'Refresh interval' => 'Default (1 minute)'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Test Item history',
'context' => ['values' => 'Simple host with item for Item history widget']
]
]
]
]
]
],
// #11.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Header is hidden',
'Show header' => false,
'Refresh interval' => 'No refresh',
'Layout' => 'Vertical',
'Advanced configuration' => true,
'New values' => 'Bottom',
'Show timestamp' => true,
'Show column header' => 'Horizontal'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #12.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Header appears',
'Show header' => true,
'Refresh interval' => '10 seconds',
'Advanced configuration' => true,
'Show column header' => 'Off'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #13.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Refresh interval' => '30 seconds'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #14.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Refresh interval' => '1 minute'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #15.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Show lines' => '1',
'Refresh interval' => '2 minutes'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #16.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Show lines' => '100',
'Refresh interval' => '10 minutes'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #17.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Refresh interval' => '15 minutes'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #18.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Refresh interval' => '10 minutes'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #19.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Override host' => 'Dashboard',
'Refresh interval' => '2 minutes'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #20.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Override host' => 'Dashboard',
'Refresh interval' => '1 minute'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #21.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => ' Widget with trimmed trailing and leading spaces ',
'Refresh interval' => '30 seconds',
'Show lines' => ' 5 '
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Test Item history',
'context' => ['values' => 'Simple host with item for Item history widget']
]
]
]
],
'trim' => ['Name', 'Show lines']
]
],
// #22.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Show header' => true,
'Name' => 'Widget with updated fields',
'Refresh interval' => '1 minute',
'Show lines' => '50',
'Override host' => 'Dashboard'
],
'Columns' => [
[
'fields' => [
'Name' => 'Column1',
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
]
]
]
]
]
],
// #23.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Empty name in column'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Available memory',
'context' => ['values' => 'ЗАББИКС Сервер']
],
'Name' => ''
]
]
],
'column_error' => 'Invalid parameter "/1/name": cannot be empty.'
]
],
// #24.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Binary column with color'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Binary item',
'context' => ['values' => 'Host for all item value types']
]
],
'xpath://input[@id="base_color"]/..' => '90CAF9',
'Show thumbnail' => true
]
]
]
],
// #25.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Character column with color and highlights'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Character item',
'context' => ['values' => 'Host for all item value types']
],
'xpath://input[@id="base_color"]/..' => 'AFB42B',
'Display' => 'HTML',
'Use monospace font' => true
],
'Highlights' => [
[
'xpath://input[@id="highlights_0_color"]/..' => '00ACC1',
'id:highlights_0_pattern' => 'pattern_1'
],
[
'xpath://input[@id="highlights_1_color"]/..' => '00ACC1',
'id:highlights_1_pattern' => 12345
]
]
]
]
]
],
// #26.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Duplicated highlights'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Character item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'HTML'
],
'Highlights' => [
[
'xpath://input[@id="highlights_0_color"]/..' => '00ACC1',
'id:highlights_0_pattern' => 'pattern_1'
],
[
'xpath://input[@id="highlights_1_color"]/..' => '0288D1',
'id:highlights_1_pattern' => 'pattern_1'
]
]
]
],
'column_error' => 'Invalid parameter "/1/highlights/2": value (pattern)=(pattern_1) already exists.'
]
],
// #27.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Character column with empty Highlight'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Character item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'HTML',
'Use monospace font' => true
],
'Highlights' => [
[
'xpath://input[@id="highlights_0_color"]/..' => '00ACC1'
]
]
]
],
'column_error' => 'Invalid parameter "/1/highlights/1/pattern": cannot be empty.'
]
],
// #28.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Character column with 0 max length'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Character item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Single line',
'Use monospace font' => true,
'id:max_length' => 0
]
]
],
'column_error' => 'Invalid parameter "/1/max_length": value must be one of 1-500.'
]
],
// #29.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Character column with text in max length'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Character item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Single line',
'Use monospace font' => true,
'id:max_length' => 'text'
]
]
],
'column_error' => 'Invalid parameter "/1/max_length": value must be one of 1-500.'
]
],
// #30.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Character column with too large max length'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Character item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Single line',
'id:max_length' => 599
]
]
],
'column_error' => 'Invalid parameter "/1/max_length": value must be one of 1-500.'
]
],
// #31.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Float column with text in min'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Bar',
'id:min' => 'min'
]
]
],
'column_error' => 'Invalid parameter "/1/min": a number is expected.'
]
],
// #32.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Float column with text in max'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Bar',
'id:max' => 'max'
]
]
],
'column_error' => 'Invalid parameter "/1/max": a number is expected.'
]
],
// #33.
[
[
'fields' => [
'Name' => 'Float column with Bar display and calculated min/max'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Bar'
]
]
]
]
],
// #34.
[
[
'fields' => [
'Name' => 'Float column with Bar display and negative min/max'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Bar',
'id:min' => -9999,
'id:max' => -20
]
]
]
]
],
// #35.
[
[
'fields' => [
'Name' => 'Float column with Bar display and float min/max'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Bar',
'id:min' => -1.5000009,
'id:max' => -30
]
]
]
]
],
// #36.
[
[
'fields' => [
'Name' => 'Unsigned column with Indicators display and float min/max'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Indicators',
'id:min' => -1.5000009,
'id:max' => -500.999
]
]
]
]
],
// #37.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Float column with Indicators display and text in min'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Indicators',
'id:min' => 'minimal'
]
]
],
'column_error' => 'Invalid parameter "/1/min": a number is expected.'
]
],
// #38.
[
[
'fields' => [
'Name' => 'Unsigned column with Indicators display and calculated min/max'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Unsigned item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Indicators'
]
]
]
]
],
// #39.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Duplicated Thresholds'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
]
],
'Thresholds' => [
[
'id:thresholds_0_threshold' => 12
],
[
'id:thresholds_1_threshold' => 12
]
]
]
],
'column_error' => 'Invalid parameter "/1/thresholds/2": value (threshold)=(12) already exists.'
]
],
// #40.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Text in Thresholds'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
]
],
'Thresholds' => [
[
'id:thresholds_0_threshold' => 'text'
]
]
]
],
'column_error' => 'Invalid parameter "/1/thresholds/1/threshold": a number is expected.'
]
],
// #41.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Float with negative Thresholds'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Bar',
'id:min' => 0,
'id:max' => 0,
'History data' => 'History'
],
'Thresholds' => [
[
'xpath://input[@id="thresholds_0_color"]/..' => '039BE5',
'id:thresholds_0_threshold' => -12
],
[
'xpath://input[@id="thresholds_1_color"]/..' => '039BE5',
'id:thresholds_1_threshold' => -500.99
],
[
'xpath://input[@id="thresholds_2_color"]/..' => '00ACC1',
'id:thresholds_2_threshold' => 20.0099
]
]
]
]
]
],
// #42.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Float with different colors Thresholds'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
],
'Display' => 'Indicators',
'id:min' => 9999999,
'id:max' => 9999999999999,
'History data' => 'Trends'
],
'Thresholds' => [
[
'xpath://input[@id="thresholds_0_color"]/..' => 'E91E63',
'id:thresholds_0_threshold' => 158
],
[
'xpath://input[@id="thresholds_1_color"]/..' => '039BE5',
'id:thresholds_1_threshold' => 19.20
]
]
]
]
]
],
// #43.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Float with empty Threshold'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Float item',
'context' => ['values' => 'Host for all item value types']
]
],
'Thresholds' => [
[
'xpath://input[@id="thresholds_0_color"]/..' => 'E91E63'
]
]
]
]
]
],
// #44.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Log item column'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Log item',
'context' => ['values' => 'Host for all item value types']
],
'Use monospace font' => true,
'Display local time' => true
]
]
]
]
],
// #45.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Text item column'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
],
'Use monospace font' => true
]
]
]
]
],
// #46.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Time period = empty widget',
'Advanced configuration' => true,
'Time period' => 'Widget'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'error' => 'Invalid parameter "Time period/Widget": cannot be empty.'
]
],
// #47.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Time period = Custom, empty from/to',
'Advanced configuration' => true,
'Time period' => 'Custom',
'From' => '',
'To' => ''
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'error' => [
'Invalid parameter "Time period/From": cannot be empty.',
'Invalid parameter "Time period/To": cannot be empty.'
]
]
],
// #48.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Time period = Custom, wrong from/to',
'Advanced configuration' => true,
'Time period' => 'Custom',
'From' => 'test_1',
'To' => 'test_2'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'error' => [
'Invalid parameter "Time period/From": a time is expected.',
'Invalid parameter "Time period/To": a time is expected.'
]
]
],
// #49.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Time period = Custom, Default from/to',
'Advanced configuration' => true,
'Time period' => 'Custom'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
]
]
],
// #50.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Time period = Custom',
'Advanced configuration' => true,
'Time period' => 'Custom',
'From' => 'now-1y',
'To' => 'now-1M'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'check_time' => 'now-1y – now-1M'
]
],
// #51.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Time period = Custom, To in future',
'Advanced configuration' => true,
'Time period' => 'Custom'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'time_shift' => true,
'check_time' => 'future'
]
],
// #52.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Time period = Custom, human readable in the past',
'Advanced configuration' => true,
'Time period' => 'Custom'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'time_shift' => true,
'check_time' => 'past'
]
],
// #53.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Time period = Custom, To < From',
'Advanced configuration' => true,
'Time period' => 'Custom',
'From' => 'now-1M',
'To' => 'now-2M'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'error' => 'Minimum time period to display is 1 minute.'
]
],
// #54.
[
[
'expected' => TEST_BAD,
'fields' => [
'Name' => 'Time period = Custom, period 30s',
'Advanced configuration' => true,
'Time period' => 'Custom'
],
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
],
'time_shift' => true,
'check_time' => 'custom',
'error' => 'Minimum time period to display is 1 minute.'
]
],
// #55.
[
[
'expected' => TEST_GOOD,
'fields' => [
'Name' => 'Time period = widget',
'Advanced configuration' => true,
'Time period' => 'Widget',
'Widget' => 'Classic graph for time period reference'
],
'clear_custom' => true,
'Columns' => [
[
'fields' => [
'Item' => [
'values' => 'Text item',
'context' => ['values' => 'Host for all item value types']
]
]
]
]
]
]
];
}
/**
* @dataProvider getWidgetData
*/
public function testDashboardItemHistoryWidget_Create($data) {
$this->checkWidgetForm($data);
}
public function testDashboardItemHistoryWidget_SimpleUpdate() {
$old_hash = CDBHelper::getHash(self::SQL);
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboard_create)->waitUntilReady();
$dashboard = CDashboardElement::find()->one();
$dashboard->getWidget(self::$update_widget)->edit()->submit();
$dashboard->save();
$this->page->waitUntilReady();
$this->assertMessage(TEST_GOOD, 'Dashboard updated');
$this->assertEquals($old_hash, CDBHelper::getHash(self::SQL));
}
/**
* @dataProvider getWidgetData
*/
public function testDashboardItemHistoryWidget_Update($data) {
$this->checkWidgetForm($data, true);
}
/**
* Perform Item history widget creation or update and verify the result.
*
* @param array $data data provider
* @param boolean $update updating is performed
*/
protected function checkWidgetForm($data, $update = false) {
$expected = CTestArrayHelper::get($data, 'expected', TEST_GOOD);
if ($expected === TEST_BAD) {
$old_hash = CDBHelper::getHash(self::SQL);
}
$data['fields']['Name'] = CTestArrayHelper::get($data, 'fields.Name', 'Item history widget '.microtime());
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboard_create)->waitUntilReady();
$dashboard = CDashboardElement::find()->one();
$old_widget_count = $dashboard->getWidgets()->count();
$form = $update
? $dashboard->getWidget(self::$update_widget)->edit()->asForm()
: $dashboard->edit()->addWidget()->asForm();
$form->fill(['Type' => CFormElement::RELOADABLE_FILL('Item history')]);
if ($update) {
$button_remove = $form->query('id:list_columns')->asTable()->one()->query('button:Remove');
$remove_count = $button_remove->count();
for ($i = 0; $i < $remove_count; $i++) {
$button_remove->waitUntilClickable()->one()->click();
$form->waitUntilReloaded();
}
}
// Reset custom period fields to defaults, because they are saved from previous cases.
if ($update && CTestArrayHelper::get($data, 'clear_custom')) {
$form->fill([
'Advanced configuration' => true,
'Time period' => 'Custom',
'From' => 'now-1h',
'To' => 'now'
]);
}
$form->fill($data['fields']);
// Fill time period with data From: now, To: now +/- time shift in human-readable format.
if (CTestArrayHelper::get($data, 'time_shift', false)) {
$time = time();
switch ($data['check_time']) {
case 'future':
$period = [
'From' => date('Y-m-d H:i:s', $time), // Now.
'To' => date('Y-m-d H:i:s', ($time + 31536000)) // Now + 1 year.
];
break;
case 'past':
$period = [
'From' => date('Y-m-d H:i:s', $time - 31536000), // Now - 1 Year.
'To' => date('Y-m-d H:i:s', ($time)) // Now.
];
break;
case 'custom':
$period = [
'From' => date('Y-m-d H:i:s', $time - 30), // Now - 30 seconds.
'To' => date('Y-m-d H:i:s', ($time)) // Now.
];
break;
}
$form->fill($period);
$data['check_time'] = $period['From'].' – '.$period['To'];
}
$values = $form->getValues();
// Fill Columns field.
if (array_key_exists('Columns', $data)) {
foreach ($data['Columns'] as $column) {
$form->getFieldContainer('Columns')->query('button:Add')->one()->waitUntilClickable()->click();
$column_overlay = COverlayDialogElement::find()->all()->last()->waitUntilReady();
$column_overlay_form = $column_overlay->asForm();
$column_overlay_form->fill($column['fields']);
foreach (['Highlights', 'Thresholds'] as $table_field) {
if (array_key_exists($table_field, $column)) {
foreach ($column[$table_field] as $highlight) {
$column_overlay_form->getFieldContainer($table_field)->query('button:Add')->one()
->waitUntilClickable()->click();
$column_overlay_form->fill($highlight);
}
}
}
$column_overlay->getFooter()->query('button:Add')->waitUntilClickable()->one()->click();
if (array_key_exists('column_error', $data)) {
break;
}
$column_overlay->waitUntilNotVisible();
$form->waitUntilReloaded();
}
}
if (!array_key_exists('column_error', $data)) {
$form->submit();
}
// Trim leading and trailing spaces from expected results if necessary.
if (array_key_exists('trim', $data)) {
foreach ($data['trim'] as $field) {
$data['fields'][$field] = trim($data['fields'][$field]);
$values[$field] = trim($data['fields'][$field]);
}
}
if ($expected === TEST_BAD) {
if (array_key_exists('column_error', $data)) {
$data['error'] = $data['column_error'];
}
$this->assertMessage($data['expected'], null, $data['error']);
$this->assertEquals($old_hash, CDBHelper::getHash(self::SQL));
// Check that after error and cancellation of the widget, the widget is not available on dashboard.
$dialogs = COverlayDialogElement::find()->all();
$dialog_count = $dialogs->count();
for ($i = $dialog_count - 1; $i >= 0; $i--) {
$dialogs->get($i)->close(true);
}
$dashboard->save()->waitUntilReady();
$this->assertMessage(TEST_GOOD, 'Dashboard updated');
$this->assertFalse($dashboard->getWidget($data['fields']['Name'], false)->isValid());
}
else {
if (array_key_exists('Name', $data['fields'])) {
$header = ($data['fields']['Name'] === '')
? 'Item history'
: $data['fields']['Name'];
}
else {
$header = $update ? self::$update_widget : 'Item history';
}
COverlayDialogElement::ensureNotPresent();
$widget = $dashboard->getWidget($header);
// Save Dashboard to ensure that widget is correctly saved.
$dashboard->save()->waitUntilReady();
$this->assertMessage(TEST_GOOD, 'Dashboard updated');
if ($update) {
self::$update_widget = $header;
}
// Check widgets count.
$this->assertEquals($old_widget_count + ($update ? 0 : 1), $dashboard->getWidgets()->count());
if (array_key_exists('check_time', $data)) {
$this->assertEquals($data['check_time'], $widget->getTimeInterval());
}
// Check new widget update interval.
$refresh = (CTestArrayHelper::get($data['fields'], 'Refresh interval', 'Default (1 minute)') === 'Default (1 minute)')
? '1 minute'
: $data['fields']['Refresh interval'];
$this->assertEquals($refresh, $widget->getRefreshInterval());
// Check new widget form fields and values in frontend.
$saved_form = $widget->edit();
// 'Advanced configuration' is always collapsed after save.
$values['Advanced configuration'] = false;
$data['fields']['Advanced configuration'] = false;
$this->assertEquals($values, $saved_form->getValues());
$table = $saved_form->query('id:list_columns')->asTable()->one();
// Count is minus one row because of Add button row.
$columns_count = $table->getRows()->count() - 1;
$this->assertEquals(count($data['Columns']), $columns_count);
foreach ($data['Columns'] as $i => $column) {
$row = $table->getRow($i);
$column_name = (array_key_exists('Name', $column['fields']))
? $column['fields']['Name']
: $column['fields']['Item']['context']['values'].': '.$column['fields']['Item']['values'];
$this->assertEquals($column_name, $row->getColumn('Name')->getText());
$this->assertEquals($column['fields']['Item']['context']['values'].': '.$column['fields']['Item']['values'],
$row->getColumn('Data')->getText()
);
}
$saved_form->checkValue($data['fields']);
// Close widget window and cancel editing the dashboard.
COverlayDialogElement::find()->one()->close();
$dashboard->cancelEditing();
}
}
public static function getCancelData() {
return [
// Cancel update widget.
[
[
'update' => true,
'save_widget' => true,
'save_dashboard' => false
]
],
[
[
'update' => true,
'save_widget' => false,
'save_dashboard' => true
]
],
// Cancel create widget.
[
[
'save_widget' => true,
'save_dashboard' => false
]
],
[
[
'save_widget' => false,
'save_dashboard' => true
]
]
];
}
/**
* @dataProvider getCancelData
*/
public function testDashboardItemHistoryWidget_Cancel($data) {
$old_hash = CDBHelper::getHash(self::SQL);
$new_name = 'Widget to be cancelled';
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid)->waitUntilReady();
$dashboard = CDashboardElement::find()->one()->edit();
$old_widget_count = $dashboard->getWidgets()->count();
// Start updating or creating a widget.
if (CTestArrayHelper::get($data, 'update', false)) {
$form = $dashboard->getWidget(self::DEFAULT_WIDGET)->edit();
}
else {
$form = $dashboard->addWidget()->asForm();
$form->fill(['Type' => CFormElement::RELOADABLE_FILL('Item history')]);
}
$form->fill([
'Name' => $new_name,
'Refresh interval' => '15 minutes'
]);
$form->getFieldContainer('Columns')->query('button:Add')->waitUntilClickable()->one()->click();
$column_overlay = COverlayDialogElement::find()->all()->last()->waitUntilReady();
$column_overlay->asForm()->fill([
'Item' => [
'values' => 'Test Item history',
'context' => ['values' => 'Simple host with item for Item history widget']
]
]);
$column_overlay->getFooter()->query('button:Add')->waitUntilClickable()->one()->click();
$column_overlay->waitUntilNotVisible();
$form->waitUntilReloaded();
// Save or cancel widget.
if (CTestArrayHelper::get($data, 'save_widget', false)) {
$form->submit();
// Check that changes took place on the unsaved dashboard.
$this->assertTrue($dashboard->getWidget($new_name)->isVisible());
}
else {
$dialog = COverlayDialogElement::find()->one();
$dialog->query('button:Cancel')->one()->click();
$dialog->ensureNotPresent();
if (CTestArrayHelper::get($data, 'update', false)) {
foreach ([self::DEFAULT_WIDGET => true, $new_name => false] as $name => $valid) {
$dashboard->getWidget($name, false)->isValid($valid);
}
}
$this->assertEquals($old_widget_count, $dashboard->getWidgets()->count());
}
// Save or cancel dashboard update.
if (CTestArrayHelper::get($data, 'save_dashboard', false)) {
$dashboard->save();
}
else {
$dashboard->cancelEditing();
}
// Check that no changes were made to the widget.
$this->assertEquals($old_hash, CDBHelper::getHash(self::SQL));
}
public function testDashboardItemHistoryWidget_Delete() {
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid)->waitUntilReady();
$dashboard = CDashboardElement::find()->one()->edit();
$widget = $dashboard->getWidget(self::DELETE_WIDGET);
$dashboard->deleteWidget(self::DELETE_WIDGET);
$widget->waitUntilNotPresent();
$dashboard->save();
$this->assertMessage(TEST_GOOD, 'Dashboard updated');
// Check that widget is not present on dashboard.
$this->assertFalse($dashboard->getWidget(self::DELETE_WIDGET, false)->isValid());
$widget_sql = 'SELECT NULL FROM widget_field wf LEFT JOIN widget w ON w.widgetid=wf.widgetid'.
' WHERE w.name='.zbx_dbstr(self::DELETE_WIDGET);
$this->assertEquals(0, CDBHelper::getCount($widget_sql));
}
public static function getTableData() {
return [
// #0 Simple test case with one item and one data entry.
[
[
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history'
]
],
'item_data' => [
['itemid' => '42227', 'values' => 'Zabbix Item history', 'time' => strtotime('Now')]
]
]
],
// #1 Simple test case with one item and several data entries.
[
[
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 minute')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history2'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-2 minutes')),
'Name' => 'Host name',
'Value' => 'Zabbix plain ⓣⓔⓧⓣ'
]
],
'item_data' => [
['itemid' => '42227', 'values' => 'Zabbix Item history', 'time' => strtotime('now')],
['itemid' => '42227', 'values' => 'Zabbix Item history2', 'time' => strtotime('-1 minute')],
['itemid' => '42227', 'values' => 'Zabbix plain ⓣⓔⓧⓣ', 'time' => strtotime('-2 minutes')]
]
]
],
// #2 Test case with two items and several data entries.
[
[
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Available memory',
'Value' => '9.37 GB' // value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-30 seconds')),
'Name' => 'Available memory in %',
'Value' => '82.0618 %' // value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 minute')),
'Name' => 'Available memory in %',
'Value' => '72.0618 %' // value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 hour')),
'Name' => 'Available memory',
'Value' => '8.44 GB' // value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-2 hours')),
'Name' => 'Available memory',
'Value' => '7.51 GB' // value rounding is expected.
]
],
'item_data' => [
['itemid' => '42243', 'values' => '8061078528', 'time' => strtotime('-2 hours')],
['itemid' => '42243', 'values' => '9061078528', 'time' => strtotime('-1 hour')],
['itemid' => '42243', 'values' => '10061078528', 'time' => strtotime('now')],
['itemid' => '42244', 'values' => '72.061797', 'time' => strtotime('-1 minute')],
['itemid' => '42244', 'values' => '82.061797', 'time' => strtotime('-30 seconds')]
]
]
],
// #3 Test case with limited lines to show.
[
[
'fields' => [
'Show lines' => '1'
],
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('today + 9 hours')),
'Name' => 'Available memory',
'Value' => '9.37 GB' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('yesterday')),
'Name' => 'Available memory',
'Value' => '8.44 GB' // Value rounding is expected.
]
],
'result' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('today + 9 hours')),
'Name' => 'Available memory',
'Value' => '9.37 GB' // Value rounding is expected.
]
],
'item_data' => [
['itemid' => '42243', 'values' => '10061078528', 'time' => strtotime('today + 9 hours')],
['itemid' => '42243', 'values' => '9061078528', 'time' => strtotime('yesterday')]
]
]
],
// #4 Test case for 'Items location' and 'Show text as HTML' options check.
[
[
'fields' => ['Layout' => 'Vertical'],
'edit_columns' => [
'Host name' => ['Display' => 'HTML']
],
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Master item',
'Value' => '1' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-15 hours')),
'Name' => 'Host name',
'Value' => ''.STRING_128.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-16 hours')),
'Name' => 'Host name',
'Value' => ''.'test'.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-25 hours')),
'Name' => 'Host name',
'Value' => STRING_255
]
],
'result' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Master item' => '1' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-15 hours')),
'Host name' => STRING_128
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-16 hours')),
'Host name' => 'TEST'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-25 hours')),
'Host name' => STRING_255
]
],
'item_data' => [
['itemid' => '99142', 'values' => '1.00001', 'time' => strtotime('now')],
['itemid' => '42227', 'values' => ''.STRING_128.'', 'time' => strtotime('-15 hours')],
['itemid' => '42227', 'values' => ''.'test'.'',
'time' => strtotime('-16 hours')
],
['itemid' => '42227', 'values' => STRING_255, 'time' => strtotime('-25 hours')]
]
]
],
// #5 Test case for 'Items location' and 'Show text as Single line' options check.
[
[
'fields' => [
'Advanced configuration' => true,
'New values' => 'Bottom',
'Show timestamp' => false
],
'edit_columns' => [
'Host name' => ['Display' => 'Single line', 'id:max_length' => 3]
],
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Master item',
'Value' => '1' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-15 hours')),
'Name' => 'Host name',
'Value' => ''.STRING_128.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-16 hours')),
'Name' => 'Host name',
'Value' => ''.'test'.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-25 hours')),
'Name' => 'Host name',
'Value' => STRING_255
]
],
'result' => [
[
'Name' => 'Host name',
'Value' => 'lon...'
],
[
'Name' => 'Host name',
'Value' => ' 'Host name',
'Value' => '...'
],
[
'Name' => 'Master item',
'Value' => '1' // Value rounding is expected.
]
],
'item_data' => [
['itemid' => '99142', 'values' => '1.00001', 'time' => strtotime('now')],
['itemid' => '42227', 'values' => ''.STRING_128.'', 'time' => strtotime('-15 hours')],
['itemid' => '42227', 'values' => ''.'test'.'',
'time' => strtotime('-16 hours')
],
['itemid' => '42227', 'values' => STRING_255, 'time' => strtotime('-25 hours')]
]
]
],
// #6 Test case for host selection check.
[
[
'host_select' => [
'without_data' => 'Simple host with item for Item history widget',
'with_data' => 'ЗАББИКС Сервер'
],
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-80 seconds')),
'Name' => 'Master item',
'Value' => '7.7778' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 week')),
'Name' => 'Host name',
'Value' => STRING_255
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 month')),
'Name' => 'Available memory in %',
'Value' => '82.0618 %' // Value rounding is expected.
]
],
'result' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 week')),
'Name' => 'Host name',
'Value' => STRING_255
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 month')),
'Name' => 'Available memory in %',
'Value' => '82.0618 %' // Value rounding is expected.
]
],
'item_data' => [
['itemid' => '42227', 'values' => 'Zabbix Item history', 'time' => strtotime('now')],
['itemid' => '99142', 'values' => '7.777777', 'time' => strtotime('-80 seconds')],
['itemid' => '42227', 'values' => STRING_255, 'time' => strtotime('-1 week')],
['itemid' => '42244', 'values' => '82.061797', 'time' => strtotime('-1 month')]
]
]
],
// #7 Test case for Auto/History options check.
[
[
'fields' => [
'Advanced configuration' => true,
'Time period' => 'Custom'
],
'edit_columns' => [
'Master item' => ['History data' => 'Auto']
],
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Master item',
'Value' => '1' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-15 hours')),
'Name' => 'Host name',
'Value' => ''.STRING_128.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-16 hours')),
'Name' => 'Host name',
'Value' => ''.'test'.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-25 hours')),
'Name' => 'Host name',
'Value' => STRING_255
]
],
'result' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-15 hours')),
'Name' => 'Host name',
'Value' => ''.STRING_128.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-16 hours')),
'Name' => 'Host name',
'Value' => ''.'test'.''
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-25 hours')),
'Name' => 'Host name',
'Value' => STRING_255
]
],
'item_data' => [
['itemid' => '99142', 'values' => '1.00001', 'time' => strtotime('now')],
['itemid' => '42227', 'values' => ''.STRING_128.'', 'time' => strtotime('-15 hours')],
['itemid' => '42227', 'values' => ''.'test'.'',
'time' => strtotime('-16 hours')
],
['itemid' => '42227', 'values' => STRING_255, 'time' => strtotime('-25 hours')]
]
]
],
// #8 Test case for Time period check.
[
[
'fields' => [
'Advanced configuration' => true,
'Time period' => 'Custom',
'From' => date('Y-m-d H:i:s', strtotime('-5 days')),
'To' => date('Y-m-d H:i:s', strtotime('now'))
],
'initial_data' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('+1 hours')),
'Name' => 'Available memory in %',
'Value' => '82.0618 %' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-80 seconds')),
'Name' => 'Master item',
'Value' => '7.7778' // Value rounding is expected.
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-1 week')),
'Name' => 'Host name',
'Value' => STRING_255
]
],
'result' => [
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('now')),
'Name' => 'Host name',
'Value' => 'Zabbix Item history'
],
[
'Timestamp' => date('Y-m-d H:i:s', strtotime('-80 seconds')),
'Name' => 'Master item',
'Value' => '7.7778' // Value rounding is expected.
]
],
'item_data' => [
['itemid' => '42227', 'values' => 'Zabbix Item history', 'time' => strtotime('now')],
['itemid' => '99142', 'values' => '7.777777', 'time' => strtotime('-80 seconds')],
['itemid' => '42227', 'values' => STRING_255, 'time' => strtotime('-1 week')],
['itemid' => '42244', 'values' => '82.061797', 'time' => strtotime('+1 hours')]
]
]
]
];
}
/**
* @backup !history, !history_uint, !history_str
*
* @dataProvider getTableData
*/
public function testDashboardItemHistoryWidget_TableData($data) {
foreach ($data['item_data'] as $params) {
CDataHelper::addItemData($params['itemid'], $params['values'], $params['time']);
}
$this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboard_data)->waitUntilReady();
$dashboard = CDashboardElement::find()->one();
$dashboard->waitUntilReady();
$this->assertTableData($data['initial_data']);
$default_values = [
'fields' => [
'Layout' => 'Horizontal',
'Show lines' => '25',
'Advanced configuration' => true,
'New values' => 'Top',
'Show timestamp' => true,
'Time period' => 'Custom',
'From' => 'now-1y',
'To' => 'now/d'
],
'columns' => [
'Host name' => ['id:display' => 'As is'],
'Master item' => ['History data' => 'History']
]
];
if (array_key_exists('fields', $data)) {
$this->widgetConfigurationChange($data['fields'], $dashboard,
CTestArrayHelper::get($data, 'edit_columns', [])
);
$this->assertTableData($data['result']);
$this->widgetConfigurationChange($default_values['fields'], $dashboard, $default_values['columns']);
}
if (array_key_exists('host_select', $data)) {
$multiselect_field = $dashboard->getControls()->query('class:multiselect-control')->asMultiselect()->one();
$multiselect_field->fill($data['host_select']['without_data']);
$dashboard->waitUntilReady();
$this->assertTableData();
$multiselect_field->fill($data['host_select']['with_data']);
$dashboard->waitUntilReady();
$this->assertTableData($data['result']);
$multiselect_field->clear();
$dashboard->waitUntilReady();
}
if (array_key_exists('result', $data)) {
$this->assertTableData($data['initial_data']);
}
}
/**
* Test function for assuring that all items are available in Item History widget.
*/
public function testDashboardItemHistoryWidget_CheckAvailableItems() {
$this->checkAvailableItems('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid,
'Item history'
);
}
/**
* Change Item history widget configuration.
*
* @param CDashboardElement $dashboard dashboard element
* @param array $configuration widget parameter(s)
* @param array $edit_columns array of columns to be changed in test
*/
protected function widgetConfigurationChange($configuration, $dashboard, $edit_columns = []) {
$form = $dashboard->getWidget(self::DATA_WIDGET)->edit();
$form->fill($configuration);
if ($edit_columns !== []) {
foreach ($edit_columns as $name => $settings) {
$form->getFieldContainer('Columns')->asTable()->findRow('Name', $name)
->query('button:Edit')->one()->click();
$column_overlay = COverlayDialogElement::find()->all()->last()->waitUntilReady();
$column_overlay->asForm()->fill($settings);
$column_overlay->getFooter()->query('button:Update')->waitUntilClickable()->one()->click();
$column_overlay->waitUntilNotVisible();
$form->waitUntilReloaded();
}
}
$form->submit();
$dashboard->getWidget(self::DATA_WIDGET);
$dashboard->save();
$dashboard->waitUntilReady();
}
/**
* Check field's hint text.
*
* @param CFormElement $form given form
* @param string $label checked field's label
* @param string $hint_text text of the hint
*/
protected function checkHint($form, $label, $hint_text) {
$form->getLabel($label)->query('xpath:./button[@data-hintbox]')->one()->click();
$hint = $this->query('xpath://div[@data-hintboxid]')->waitUntilVisible();
$this->assertEquals($hint_text, $hint->one()->getText());
$hint->one()->query('xpath:.//button[@class="btn-overlay-close"]')->one()->click();
$hint->waitUntilNotPresent();
}
/**
* Check Thresholds or Highlights field inputs and color-pickers.
*
* @param CFormElement $form given form
* @param string $label checked field's label
* @param int $i input counter
* @param string $selector selector of tested input
*/
protected function checkThresholdsHighlights($form, $label, $i, $selector) {
$container = $form->getFieldContainer($label);
$container->query('button:Add')->one()->click();
$input = $form->query('xpath:.//input[contains(@id, '.CXPathHelper::escapeQuotes($i.$selector).')]')->one();
$this->assertTrue($input->isVisible());
$this->assertEquals('FF465C', $container->query('xpath:.//div[@class="color-picker"]')
->asColorPicker()->one()->getValue()
);
$container->query('xpath:.//button[contains(@id, '.CXPathHelper::escapeQuotes($i.'_remove').')]')
->one()->click();
$this->assertFalse($input->isVisible());
}
}