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.

2301 lines
62 KiB

1 year ago
<?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__).'/../../include/helpers/CDataHelper.php';
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
require_once dirname(__FILE__).'/../traits/PreprocessingTrait.php';
use Facebook\WebDriver\Exception\ElementClickInterceptedException;
/**
* Test the mass update of items and item prototypes.
*
* @backup items, interface
*/
class testMassUpdateItems extends CWebTest{
use PreprocessingTrait;
const HOSTID = 40001; // Simple form test host.
const RULEID = 133800; // testFormDiscoveryRule1 on Simple form test host.
const HOST_NAME = 'Simple form test host';
const AGENT_INTERFACE_ID = 40011;
const SNMP2_INTERFACE_ID = 40012;
const IPMI_INTERFACE_ID = 40013;
const INTERVAL_MAPPING = [
'Type' => [
'name' => 'type',
'class' => 'CSegmentedRadioElement',
'selector' => 'xpath:./ul[contains(@class, "radio-list-control")]'.
'|./ul/li/ul[contains(@class, "radio-list-control")]|./div/ul[contains(@class, "radio-list-control")]'
],
'Interval' => [
'name' => 'delay',
'class' => 'CElement',
'selector' => 'xpath:./input[@name][not(@type) or @type="text" or @type="password"][not(@style) or '.
'not(contains(@style,"display: none"))]|./textarea[@name]'
],
'Period' => [
'name' => 'period',
'class' => 'CElement',
'selector' => 'xpath:./input[@name][not(@type) or @type="text" or @type="password"][not(@style) or '.
'not(contains(@style,"display: none"))]|./textarea[@name]'
]
];
/**
* Attach MessageBehavior to the test.
*
* @return array
*/
public function getBehaviors() {
return ['class' => CMessageBehavior::class];
}
/**
* Add interface to host.
*/
public function prepareInterfaceData() {
CDataHelper::call('hostinterface.create', [
[
'hostid' => self::HOSTID,
'dns' => '',
'ip' => '127.0.5.5',
'main' => 0,
'port' => '10055',
'type' => 2,
'useip' => 1,
'details' => [
'version' => 3,
'bulk' => 1,
'max_repetitions' => 10,
'securityname' => 'zabbix',
'securitylevel' => 0,
'authprotocol' => 0,
'privprotocol' => 0,
'contextname' => 'zabbix'
]
]
]);
}
/**
* Data for mass updating of items and item prototypes.
*/
public function getCommonChangeData() {
return [
// #0.
[
[
'expected' => TEST_BAD,
'names' => [
'7_IPMI',
'8_IPMI'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SNMP agent']
],
'details' => 'Invalid parameter "/1/snmp_oid": cannot be empty.'
]
],
// #1.
[
[
'expected' => TEST_BAD,
'names' => [
'13_DB_Monitor',
'14_DB_Monitor'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'TELNET agent']
],
'details' => 'Invalid parameter "/2/username": cannot be empty.'
]
],
// #2.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'TELNET agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051']
],
'details' => 'Invalid parameter "/1/username": cannot be empty.'
]
],
// #3.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SSH agent'],
'Authentication method' => ['id' => 'authtype', 'value' => 'Password'],
'User name' => ['id' => 'username', 'value' => '']
],
'details' => 'Invalid parameter "/1/username": cannot be empty.'
]
],
// #4.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SSH agent'],
'Authentication method' => ['id' => 'authtype', 'value' => 'Public key'],
'User name' => ['id' => 'username', 'value' => ''],
'Public key file' => ['id' => 'publickey', 'value' => '/path/file1'],
'Private key file' => ['id' => 'privatekey', 'value' => '/path/file2']
],
'details' => 'Invalid parameter "/1/username": cannot be empty.'
]
],
// #5.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SSH agent'],
'Authentication method' => ['id' => 'authtype', 'value' => 'Public key'],
'User name' => ['id' => 'username', 'value' => 'new_test_name'],
'Public key file' => ['id' => 'publickey', 'value' => ''],
'Private key file' => ['id' => 'privatekey', 'value' => '/path/file2']
],
'details' => 'Invalid parameter "/1/publickey": cannot be empty.'
]
],
// #6.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SSH agent'],
'Authentication method' => ['id' => 'authtype', 'value' => 'Public key'],
'User name' => ['id' => 'username', 'value' => 'new_test_name'],
'Public key file' => ['id' => 'publickey', 'value' => '/path/file1'],
'Private key file' => ['id' => 'privatekey', 'value' => '']
],
'details' => 'Invalid parameter "/1/privatekey": cannot be empty.'
]
],
// #7.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '3599']
]
],
'details' => 'Invalid parameter "/1/history": value must be one of 0, 3600-788400000.'
]
],
// #8.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '1']
]
],
'details' => 'Invalid parameter "/1/history": value must be one of 0, 3600-788400000.'
]
],
// #9.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '']
]
],
'details' => 'Invalid parameter "/1/history": cannot be empty.'
]
],
// #10.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '25y']
]
],
'details' => 'Invalid parameter "/1/history": a time unit is expected.'
]
],
// #11.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '']
]
],
'details' => 'Invalid parameter "/1/trends": cannot be empty.'
]
],
// #12.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '86399']
]
],
'details' => 'Invalid parameter "/1/trends": value must be one of 0, 86400-788400000.'
]
],
// #13.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '1']
]
],
'details' => 'Invalid parameter "/1/trends": value must be one of 0, 86400-788400000.'
]
],
// #14.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '25y']
]
],
'details' => 'Invalid parameter "/1/trends": a time unit is expected.'
]
],
// #15.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix trapper'],
'Allowed hosts' => ['id' => 'trapper_hosts', 'value' => 'Zabbix server']
],
'details' => 'Invalid parameter "/1/trapper_hosts": invalid address range "Zabbix server".'
]
],
// #16.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Update interval' => ['Delay' => '']
],
'details' => 'Invalid parameter "/1/delay": cannot be empty.'
]
],
// #17.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Update interval' => ['Delay' => '0']
],
'details' => 'Invalid parameter "/1/delay": cannot be equal to zero without custom intervals.'
]
],
// #18.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Update interval' => ['Delay' => '86401']
],
'details' => 'Invalid parameter "/1/delay": value must be one of 0-86400.'
]
],
// #19.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Update interval' => [
'Delay' => '1d',
'Custom intervals' => [
[
'type' => 'Flexible',
'delay' => '99s',
'period' => ''
]
]
]
],
'details' => 'Invalid interval "".'
]
],
// #20.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Update interval' => [
'Delay' => '1s',
'Custom intervals' => [
[
'type' => 'Flexible',
'delay' => '',
'period' => '1-5,00:00-1:00'
]
]
]
],
'details' => 'Invalid interval "".'
]
],
// #21.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Update interval' => [
'Delay' => '24h',
'Custom intervals' => [
[
'type' => 'Scheduling',
'delay' => 'test'
]
]
]
],
'details' => 'Invalid interval "test".'
]
],
// #22.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => 'https//:zabbix.com'],
'Headers' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'name' => '',
'value' => 'header value 1'
]
]
],
'details' => 'Invalid parameter "/1/headers": nonempty key and value pair expected.'
]
],
// #23.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => 'https//:zabbix.com'],
'Headers' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'name' => 'header name 1',
'value' => ''
]
]
],
'details' => 'Invalid parameter "/1/headers": nonempty key and value pair expected.'
]
],
// #24.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => 'https//:zabbix.com'],
'Request body type' => ['id' => 'post_type_container', 'value' => 'JSON data'],
'Request body' => ['id' => 'posts', 'value' => '"request": "active checks", "host": "host"']
],
'details' => 'Invalid parameter "/1/posts": JSON is expected.'
]
],
// #25.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => 'https//:zabbix.com'],
'Request body type' => ['id' => 'post_type_container', 'value' => 'XML data'],
'Request body' => ['id' => 'posts', 'value' => 'xml version="1.0" encoding="UTF-8"?<zabbix_export></zabbix_export>']
],
'details' => 'Invalid parameter "/1/posts": (4) Start tag expected, \'<\' not found [Line: 1 | Column: 1].'
]
],
// #26.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => 'https//:zabbix.com'],
'Request body type' => ['id' => 'post_type_container', 'value' => 'XML data'],
'Request body' => ['id' => 'posts', 'value' => '']
],
'details' => 'Invalid parameter "/1/posts": cannot be empty.'
]
],
// #27.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => '']
],
'details' => 'Invalid parameter "/1/url": cannot be empty.'
]
],
// #28.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'JMX agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.4:10054'],
'JMX endpoint' => ['id' => 'jmx_endpoint', 'value' => '']
],
'details' => 'Invalid parameter "/1/jmx_endpoint": cannot be empty.'
]
],
// #29.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'JMX agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.4:10054'],
'JMX endpoint' => [
'id' => 'jmx_endpoint',
'value' => 'service:jmx:rmi:///jndi/rmi://{HOST.CONN}:{HOST.PORT}/jmxrmi'
],
'User name' => ['id' => 'username', 'value' => 'new_test_name'],
'Password' => ['id' => 'password', 'value' => '']
],
'details' => 'Invalid parameter "/1": both username and password should be either present or empty.'
]
],
// #30.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'JMX agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.4:10054'],
'JMX endpoint' => [
'id' => 'jmx_endpoint',
'value' => 'service:jmx:rmi:///jndi/rmi://{HOST.CONN}:{HOST.PORT}/jmxrmi'
],
'User name' => ['id' => 'username', 'value' => ''],
'Password' => ['id' => 'password', 'value' => 'new_test_password']
],
'details' => 'Invalid parameter "/1": both username and password should be either present or empty.'
]
],
// #31.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SNMP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.5:10055']
],
'details' => 'Invalid parameter "/1/snmp_oid": cannot be empty.',
'interface_text_part' => 'SNMPv3, Context name: zabbix'
]
],
// #32.
[
[
'expected' => TEST_BAD,
'names' => [
'17_Script',
'18_Script'
],
'change' => [
'Timeout' => ['id' => 'timeout', 'value' => '0']
],
'details' => 'Invalid parameter "/1/timeout": value must be one of 1-60.'
]
],
// #33.
[
[
'expected' => TEST_BAD,
'names' => [
'17_Script',
'18_Script'
],
'change' => [
'Timeout' => ['id' => 'timeout', 'value' => '61']
],
'details' => 'Invalid parameter "/1/timeout": value must be one of 1-60.'
]
],
// #34.
[
[
'expected' => TEST_BAD,
'names' => [
'17_Script',
'18_Script'
],
'change' => [
'Timeout' => ['id' => 'timeout', 'value' => '']
],
'details' => 'Invalid parameter "/1/timeout": cannot be empty.'
]
],
// #35.
[
[
'names' => [
'17_Script',
'18_Script'
],
'change' => [
'Timeout' => ['id' => 'timeout', 'value' => '60s']
]
]
],
// #36.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent (active)'],
'Type of information' => ['id' => 'value_type', 'value' => 'Numeric (float)'],
'Units' => ['id' => 'units', 'value' => '$'],
'Update interval' => [
'Delay' => '99s',
'Custom intervals' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'type' => 'Flexible',
'delay' => '60s',
'period' => '2-5,3:00-17:00'
],
[
'type' => 'Scheduling',
'delay' => 'wd3-4h1-15'
]
]
],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '400d']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Do not keep trends']
],
'Value mapping' => ['id' => 'valuemapid', 'value' => 'Reference valuemap'],
'Description' => ['id' => 'description', 'value' => 'New mass updated description']
]
]
],
// #37.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '0']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '0']
]
]
]
],
// #38.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '3600']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '86400']
]
]
]
],
// #39.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '9125d']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '9125d']
]
]
]
],
// #40.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '219000h']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '219000h']
]
]
]
],
// #41.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Storage period'],
'input' => ['id' => 'history', 'value' => '13140000m']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '13140000m']
]
]
]
],
// #42.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Simple check'],
'Type of information' => ['id' => 'value_type', 'value' => 'Log'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.2:10052'],
'User name' => ['id' => 'username', 'value' => 'test_username'],
'Password' => ['id' => 'password', 'value' => 'test_password'],
'Log time format' => ['id' => 'logtimefmt', 'value' => 'PPPPPP:YYYYMMDD:HHMMSS.mmm']
],
'interface_text_part' => 'SNMPv2, Community: {$SNMP_COMMUNITY}'
]
],
// #43.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix internal'],
'Type of information' => ['id' => 'value_type', 'value' => 'Text'],
'Update interval' => [
'Delay' => '1d',
'Custom intervals' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'type' => 'Scheduling',
'delay' => 'wd3-4h1-15'
],
[
'type' => 'Flexible',
'delay' => '99s',
'period' => '1-2,7:00-8:00'
]
]
]
]
]
],
// #44.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix trapper'],
'Type of information' => ['id' => 'value_type', 'value' => 'Numeric (unsigned)'],
'Allowed hosts' => ['id' => 'trapper_hosts', 'value' => '127.0.0.1']
]
]
],
// #45.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix trapper'],
'Allowed hosts' => ['id' => 'trapper_hosts', 'value' => '{HOST.HOST}']
]
]
],
// #46.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix trapper'],
'Allowed hosts' => [
'id' => 'trapper_hosts',
'value' => '192.168.1.0/24, 192.168.3.1-255, 192.168.1-10.1-255, ::1,2001:db8::/32, zabbix.domain'
]
]
]
],
// #47.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'External check'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'Update interval' => ['Delay' => '1440m']
]
]
],
// #48.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'HTTP agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051'],
'URL' => ['id' => 'url', 'value' => 'https//:zabbix.com'],
'Request body type' => ['id' => 'post_type_container', 'value' => 'JSON data'],
'Request body' => ['id' => 'posts', 'value' => '{"request": "active checks", "host": "host"}'],
'Headers' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'name' => 'header name 1',
'value' => 'header value 1'
],
[
'name' => 'header name 2',
'value' => 'header value 2'
]
],
'Type of information' => ['id' => 'value_type', 'value' => 'Numeric (float)'],
'Units' => ['id' => 'units', 'value' => 'kB'],
'Update interval' => ['Delay' => '86400'],
'Enable trapping' => ['id' => 'allow_traps', 'value' => 'Yes']
]
],
'screenshot' => true
],
// #49.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'JMX agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.4:10054'],
'JMX endpoint' => [
'id' => 'jmx_endpoint',
'value' => 'service:jmx:rmi:///jndi/rmi://{HOST.CONN}:{HOST.PORT}/jmxrmi'
]
]
]
],
// #50.
[
[
'names' => [
'1_Item',
'2_Item'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Zabbix agent'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.1:10051']
]
]
],
// #51.
[
[
'names' => [
'7_IPMI',
'8_IPMI'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'IPMI agent'],
'Type of information' => ['id' => 'value_type', 'value' => 'Numeric (float)'],
'Units' => ['id' => 'units', 'value' => 'kB'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.3:10053']
]
]
],
// #52.
[
[
'names' => [
'3_SNMP_trap',
'4_SNMP_trap'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SNMP trap'],
'Type of information' => ['id' => 'value_type', 'value' => 'Numeric (float)'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.5:10055'],
'History storage period' => [
'radio' => ['id' => 'history_mode', 'value' => 'Do not keep history']
],
'Trend storage period' => [
'radio' => ['id' => 'trends_mode', 'value' => 'Storage period'],
'input' => ['id' => 'trends', 'value' => '99d']
]
],
'interface_text_part' => 'SNMPv3, Context name: zabbix'
]
],
// #53.
[
[
'names' => [
'9_SNMP_Agent',
'10_SNMP_Agent'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SNMP agent'],
'Type of information' => ['id' => 'value_type', 'value' => 'Character'],
'Host interface' => ['id' => 'interface-select', 'value' => '127.0.5.5:10055']
],
'interface_text_part' => 'SNMPv3, Context name: zabbix'
]
],
// #54.
[
[
'names' => [
'11_SSH_Agent',
'12_SSH_Agent'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SSH agent'],
'Authentication method' => ['id' => 'authtype', 'value' => 'Public key'],
'User name' => ['id' => 'username', 'value' => 'new_name'],
'Public key file' => ['id' => 'publickey', 'value' => '/path/file1'],
'Private key file' => ['id' => 'privatekey', 'value' => '/path/file2']
]
]
],
// #55.
[
[
'names' => [
'11_SSH_Agent',
'12_SSH_Agent'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'SSH agent'],
'Authentication method' => ['id' => 'authtype', 'value' => 'Password'],
'User name' => ['id' => 'username', 'value' => 'New_user_name'],
'Password' => ['id' => 'password', 'value' => 'New_password']
]
]
],
// #56.
[
[
'names' => [
'13_DB_Monitor',
'14_DB_Monitor'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Database monitor'],
'User name' => ['id' => 'username', 'value' => 'db_monitor_name'],
'Password' => ['id' => 'password', 'value' => 'db_monitor_password']
],
'expected_preprocessing' => [
'13_DB_Monitor' => [
[
'type' => 'Regular expression',
'parameter_1' => 'regular expression pattern',
'parameter_2' => 'output template',
'error_handler' => 'Set value to',
'error_handler_params' => 'Error custom value'
]
],
'14_DB_Monitor' => [
[
'type' => 'Custom multiplier',
'parameter_1' => '2'
]
]
]
]
],
// TODO: uncomment or delete after discussion
// [
// [
// 'names' => [
// '1_Item',
// '2_Item'
// ],
// 'change' => [
// 'Type' => ['id' => 'type', 'value' => 'TELNET agent'],
// 'User name' => ['id' => 'username', 'value' => 'telnet_name'],
// 'Password' => ['id' => 'password', 'value' => 'telnet_password']
// ]
// ]
// ],
// [
// [
// 'names' => [
// '1_Item',
// '2_Item'
// ],
// 'change' => [
// 'Type' => ['id' => 'type', 'value' => 'Calculated'],
// 'Type of information' => ['id' => 'value_type', 'value' => 'Numeric (float)']
// ]
// ]
// ],
// #57.
[
[
'names' => [
'15_Calculated',
'16_Calculated'
],
'change' => [
'Type' => ['id' => 'type', 'value' => 'Dependent item'],
'Master item' => ['id' => 'master_item', 'value' => '7_IPMI']
],
'expected_tags' => [
'15_Calculated' => [
[
'tag' => 'Item_tag_name',
'value' => 'Item_tag_value'
]
],
'16_Calculated' =>[
[
'tag' => 'Item_tag_name_1',
'value' => 'Item_tag_value_1'
],
[
'tag' => 'Item_tag_name_2',
'value' => 'Item_tag_value_2'
]
]
]
]
]
];
}
/**
* Mass update of form fields for items or item prototypes.
*
* @param array $data data provider
* @param boolean $prototypes true if item prototype, false if item
*/
public function executeItemsMassUpdate($data, $prototypes = false) {
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
$old_hash = CDBHelper::getHash('SELECT * FROM items ORDER BY itemid');
}
$form = $this->openMassUpdateForm($prototypes, $data['names'])->asForm();
// Set field value.
foreach ($data['change'] as $field => $value) {
// Click on a label to show input control.
$form->getLabel($field)->click();
// Set field value.
switch ($field) {
case 'Type':
case 'Type of information':
case 'Authentication method':
$form->query('id', $value['id'])->asDropdown()->one()->select($value['value']);
break;
case 'Host interface':
/**
* The value of an SNMP interface option element contains not only the IP and port, but also the
* interface type and context name or community. In this case the address and details must be merged.
*/
$interface = $value['value'].CTestArrayHelper::get($data, 'interface_text_part', '');
$form->query('id', $value['id'])->asDropdown()->one()->select($interface);
break;
case 'Units':
case 'Description':
case 'User name':
case 'Password':
case 'Log time format':
case 'Allowed hosts':
case 'Request body' :
case 'URL':
case 'JMX endpoint':
case 'Public key file':
case 'Private key file':
case 'Timeout':
$form->query('id', $value['id'])->one()->fill($value['value']);
break;
case 'Request body type':
case 'Discover':
case 'Enable trapping':
case 'Create enabled':
case 'Status':
$form->query('id', $value['id'])->one()->asSegmentedRadio()->fill($value['value']);
break;
case 'Update interval':
$container_table = $form->query('id:update_interval')->asTable()->one();
$container_table->getRow(0)->getColumn(1)->query('id:delay')->one()->fill($value['Delay']);
if (array_key_exists('Custom intervals', $value)) {
$container_table->getRow(1)->getColumn(1)->query('id:custom_intervals')->asMultifieldTable(
['mapping' => self::INTERVAL_MAPPING])->one()->fill($value['Custom intervals']
);
}
break;
case 'History storage period':
case 'Trend storage period':
$form->query('id', $value['radio']['id'])->one()->asSegmentedRadio()->fill($value['radio']['value']);
if (array_key_exists('input', $value)) {
$form->query('id', $value['input']['id'])->one()->fill($value['input']['value']);
}
if ($value['radio']['value'] === 'Do not keep history') {
$this->assertFalse($form->query('id:history')->one()->isVisible());
}
break;
case 'Headers':
$form->query('xpath:.//div[@id="headers_pairs"]/table')->asMultifieldTable()->one()->fill($value);
// Take a screenshot to test draggable object position of headers in mass update.
if (array_key_exists('screenshot', $data)) {
$this->page->removeFocus();
$this->assertScreenshot($form->query('id:headers_pairs')->waitUntilPresent()->one(), 'Item mass update headers'.$prototypes);
}
break;
case 'Master item':
if ($prototypes) {
$form->query('button:Select prototype')->one()->click();
$master_dialog = COverlayDialogElement::find()->all()->last()->waitUntilReady();
$master_dialog->query('link', $value['value'])->one()->waitUntilClickable()->click();
}
else {
$form->query('id', $value['id'])->one()->asMultiselect()
->setFillMode(CMultiselectElement::MODE_SELECT)->fill($value['value']);
}
break;
case 'Value mapping':
$form->getField('Value mapping')->edit();
COverlayDialogElement::find()->one()->waitUntilReady()->query('xpath://a[text()="'.$value['value'].'"]')
->one()->waitUntilClickable()->click();
break;
}
}
$this->query('button:Update')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
$this->assertMessage(TEST_BAD, ($prototypes ? 'Cannot update item prototypes' : 'Cannot update items'),
$data['details']
);
$this->assertEquals($old_hash, CDBHelper::getHash('SELECT * FROM items ORDER BY itemid'));
}
else {
$this->assertMessage(TEST_GOOD, ($prototypes ? 'Item prototypes updated' : 'Items updated'));
// Check changed fields in saved item form.
foreach ($data['names'] as $name) {
$table = $this->query('xpath://form[@name="items"]/table[@class="list-table"]')->asTable()->one();
$table->query('link', $name)->one()->waitUntilClickable()->click();
$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
foreach ($data['change'] as $field => $value) {
switch ($field) {
case 'Type':
case 'Host interface':
case 'Type of information':
case 'Show value':
case 'Units':
case 'Description':
case 'Allowed hosts':
case 'Request body':
case 'URL':
case 'JMX endpoint':
case 'Authentication method':
case 'Public key file':
case 'Private key file':
case 'Request body type':
case 'User name':
case 'Password':
case 'Log time format':
case 'Timeout':
$this->assertEquals($value['value'], $form->getField($field)->getValue());
break;
case 'History storage period':
case 'Trend storage period':
if (CTestArrayHelper::get($value, 'input.value', 'null') === '0') {
$this->assertEquals('Do not keep '.$value['input']['id'],
$form->query('id',$value['radio']['id'])->one()->asSegmentedRadio()->getValue()
);
}
else {
$this->assertEquals($value['radio']['value'],
$form->query('id', $value['radio']['id'])->one()->asSegmentedRadio()->getValue()
);
if ($value['radio']['value'] === 'Do not keep history') {
$this->assertFalse($form->query('id:history')->one()->isVisible());
}
if (array_key_exists('input', $value)) {
$this->assertEquals($value['input']['value'],
$form->query('id', $value['input']['id'])->one()->getValue()
);
}
}
break;
case 'Status':
case 'Discover':
case 'Create enabled':
case 'Enable trapping':
$status = ($value['value'] === 'Enabled' || $value['value'] === 'Yes') ? true : false;
$label = ($field === 'Status') ? 'Enabled' : $field;
$this->assertEquals($status, $form->getField($label)->getValue());
break;
case 'Update interval':
$this->assertEquals($value['Delay'], $form->getField($field)->getValue());
if (array_key_exists('Custom intervals', $value)) {
// Remove action and index fields.
foreach($value['Custom intervals'] as &$interval) {
unset($interval['action'], $interval['index']);
}
unset($interval);
$this->assertEquals($value['Custom intervals'], $form->query('id:delayFlexTable')
->asMultifieldTable(['mapping' => self::INTERVAL_MAPPING])->one()->getValue()
);
}
break;
case 'Headers':
// Remove action and index fields.
foreach ($value as &$header) {
unset($header['action'], $header['index']);
}
unset($header);
$this->assertEquals($value, $form->query('xpath:.//div[@id="headers_pairs"]/table')
->asMultifieldTable()->one()->getValue()
);
break;
case 'Master item':
if ($prototypes) {
$this->assertEquals(self::HOST_NAME.': '.$value['value'],
$form->query('xpath://input[@id="master_itemname"]')->one()->getValue()
);
}
else {
$this->assertEquals([self::HOST_NAME.': '.$value['value']],
$form->query('xpath://*[@id="master_itemid"]/..')->asMultiselect()->one()->getValue()
);
}
break;
case 'Value mapping':
$this->assertEquals([$value['value']],
$form->query('xpath://*[@id="'.$value['id'].'"]/..')->asMultiselect()->one()->getValue()
);
break;
}
}
// Check that preprocessing is not changed after other fields are mass updated.
if (CTestArrayHelper::get($data, 'expected_preprocessing')) {
$form->selectTab('Preprocessing');
$this->assertPreprocessingSteps($data['expected_preprocessing'][$name]);
}
// Check that tags are not changed after other fields are mass updated.
if (CTestArrayHelper::get($data, 'expected_tags')) {
$form->selectTab('Tags');
$this->query('class:tags-table')->asMultifieldTable()->one()->checkValue($data['expected_tags'][$name]);
}
$form->query('button:Cancel')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
}
}
}
/**
* Add items with preprocessing for mass updating.
*/
public function prepareItemPreprocessingData() {
CDataHelper::call('item.create', [
[
'hostid' => self::HOSTID,
'name' => '1_Item_Preprocessing',
'key_' => '1agent.preproc',
'type' => 0,
'value_type' => 0,
'interfaceid' => self::AGENT_INTERFACE_ID,
'delay' => '1m',
'preprocessing' => [
[
'type' => '4',
'params' => '123',
'error_handler' => 0,
'error_handler_params' => ''
],
[
'type' => '25',
'params' => "error\nmistake",
'error_handler' => 0,
'error_handler_params' => ''
]
]
],
[
'hostid' => self::HOSTID,
'name' => '2_Item_Preprocessing',
'key_' => '2agent.preproc',
'type' => 0,
'value_type' => 1,
'interfaceid' => self::AGENT_INTERFACE_ID,
'delay' => '2m',
'preprocessing' => [
[
'type' => '5',
'params' => "pattern\noutput",
'error_handler' => 2,
'error_handler_params' => 'custom_value'
],
[
'type' => '16',
'params' => '$path',
'error_handler' => 3,
'error_handler_params' => 'custom_error'
]
]
],
[
'hostid' => self::HOSTID,
'name' => '1_Item_No_Preprocessing',
'key_' => '1agent.no.preproc',
'type' => 0,
'value_type' => 0,
'interfaceid' => self::AGENT_INTERFACE_ID,
'delay' => '1m'
],
[
'hostid' => self::HOSTID,
'name' => '2_Item_No_Preprocessing',
'key_' => '2agent.no.preproc',
'type' => 0,
'value_type' => 1,
'interfaceid' => self::AGENT_INTERFACE_ID,
'delay' => '2m'
]
]);
}
public function getCommonPreprocessingChangeData() {
return [
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'Custom multiplier', 'parameter_1' => 'abc']
],
'details' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.'
]
],
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'Simple change'],
['type' => 'Simple change']
],
'details' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within the '.
'combinations of (type)=((9, 10)).'
]
],
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'In range', 'parameter_1' => '8', 'parameter_2' => '-8']
],
'details' => 'Invalid parameter "/1/preprocessing/1/params/2": cannot be less than or equal to '.
'the value of parameter "/1/preprocessing/1/params/1".'
]
],
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'Check for error using regular expression', 'parameter_1' => 'test']
],
'details' => 'Invalid parameter "/1/preprocessing/1/params/2": cannot be empty.'
]
],
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'Discard unchanged'],
['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1']
],
'details' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within the '.
'combinations of (type)=((19, 20)).'
]
],
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'Regular expression']
],
'details' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.'
]
],
[
[
'expected' => TEST_BAD,
'names' => [
'2_Item_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
[
'type' => 'XML XPath',
'parameter_1' => "//path/one",
'on_fail' => true,
'error_handler' => 'Set error to'
]
],
'details' => 'Invalid parameter "/1/preprocessing/1/error_handler_params": cannot be empty.'
]
],
[
[
'names' => [
'1_Item_Tags_Preprocessing',
'2_Item_Tags_Preprocessing'
],
'Preprocessing steps' => []
]
],
[
[
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Preprocessing steps' => [
[
'type' => 'Custom multiplier',
'parameter_1' => '3',
'on_fail' => true,
'error_handler' => 'Set error to',
'error_handler_params' => 'New_error1'
],
[
'type' => 'In range',
'parameter_1' => '10',
'parameter_2' => '20',
'on_fail' => true,
'error_handler' => 'Set value to',
'error_handler_params' => 'New_value_2'
],
[
'type' => 'JSONPath',
'parameter_1' => '$path',
'on_fail' => true,
'error_handler' => 'Discard value'
],
[
'type' => 'Discard unchanged'
]
]
]
],
[
[
'names' => [
'1_Item_Tags_Preprocessing',
'2_Item_Tags_Preprocessing'
],
'Preprocessing steps' => [
['type' => 'Replace', 'parameter_1' => 'text', 'parameter_2' => 'REPLACEMENT'],
['type' => 'Right trim', 'parameter_1' => 'abc'],
['type' => 'Left trim', 'parameter_1' => 'def'],
['type' => 'Trim', 'parameter_1' => '1a2b3c'],
['type' => 'CSV to JSON','parameter_1' => ' ', 'parameter_2' => '\\', 'parameter_3' => true],
['type' => 'Custom multiplier', 'parameter_1' => '123'],
['type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => 'test output'],
['type' => 'Boolean to decimal'],
['type' => 'Octal to decimal'],
['type' => 'Hexadecimal to decimal'],
['type' => 'JavaScript', 'parameter_1' => 'Test JavaScript'],
['type' => 'Simple change'],
['type' => 'In range', 'parameter_1' => '-5', 'parameter_2' => '9.5'],
['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '5'],
['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label',
'parameter_3' => 'label_name']
],
'Screenshot' => true
]
]
];
}
/**
* Mass update of preprocessing steps for items or item prototypes.
*
* @param array $data data provider
* @param boolean $prototypes true if item prototype, false if item
*/
public function executeItemsPreprocessingMassUpdate($data, $prototypes = false) {
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
$old_hash = CDBHelper::getHash('SELECT * FROM items ORDER BY itemid');
}
$dialog = $this->openMassUpdateForm($prototypes, $data['names']);
$form = $dialog->asForm();
$form->selectTab('Preprocessing');
$form->getLabel('Preprocessing steps')->click();
if ($data['Preprocessing steps'] !== []) {
$this->addPreprocessingSteps($data['Preprocessing steps']);
// Take a screenshot to test draggable object position of preprocessing steps in mass update.
if (array_key_exists('Screenshot', $data)) {
$this->page->removeFocus();
// It is necessary because of unexpected viewport shift.
$this->page->updateViewport();
$this->assertScreenshot($form->query('id:preprocessing')->waitUntilPresent()->one(), 'Item mass update preprocessing'.$prototypes);
}
}
$dialog->query('button:Update')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
$error = $prototypes ? 'Cannot update item prototypes' : 'Cannot update items';
$this->assertMessage(TEST_BAD, $error, $data['details']);
$this->assertEquals($old_hash, CDBHelper::getHash('SELECT * FROM items ORDER BY itemid'));
}
else {
$this->assertMessage(TEST_GOOD, ($prototypes ? 'Item prototypes updated' : 'Items updated'));
// Check changed fields in saved item form.
foreach ($data['names'] as $name) {
$table = $this->query('xpath://form[@name="items"]/table[@class="list-table"]')->asTable()->one();
// TODO: not stable test testPageMassUpdateItems_ChangePreprocessing#8 on Jenkins, failed to properly waitUntilReady for page
try {
$table->query('link', $name)->one()->waitUntilClickable()->click();
}
catch (ElementClickInterceptedException $e) {
$table->query('link', $name)->one()->waitUntilClickable()->click();
}
$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
$form->selectTab('Preprocessing');
$this->assertPreprocessingSteps($data['Preprocessing steps']);
$form->query('button:Cancel')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
}
}
}
public function getCommonTagsChangeData() {
return [
// Empty tag name.
[
[
'expected' => TEST_BAD,
'names' => [
'1_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Add',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'value' => 'value1'
]
]
],
'details' => 'Invalid parameter "/1/tags/2/tag": cannot be empty.'
]
],
// TODO: Uncomment this case when ZBX-19263 is fixed.
// Equal tags.
/*
[
[
'expected' => TEST_BAD,
'names' => [
'2_Item_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'tag',
'value' => 'value'
],
[
'tag' => 'tag',
'value' => 'value'
]
],
'details' => 'Invalid parameter "/1/tags/2": value (tag, value)=(tag, value) already exists.'
]
],
*/
[
[
'names' => [
'1_Item_Tags_Preprocessing',
'2_Item_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Add',
'tags' => []
],
'expected_tags' => [
'1_Item_Tags_Preprocessing' => [
[
'tag' => 'old_tag_1',
'value' => 'old_value_1'
]
],
'2_Item_Tags_Preprocessing' => [
[
'tag' => 'old_tag_2',
'value' => 'old_value_2'
],
[
'tag' => 'old_tag_3',
'value' => 'old_value_3'
]
]
]
]
],
[
[
'names' => [
'1_Item_Tags_Preprocessing',
'2_Item_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Add',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'added_tag_1',
'value' => 'added_value_1'
]
]
],
'expected_tags' => [
'1_Item_Tags_Preprocessing' => [
[
'tag' => 'added_tag_1',
'value' => 'added_value_1'
],
[
'tag' => 'old_tag_1',
'value' => 'old_value_1'
]
],
'2_Item_Tags_Preprocessing' => [
[
'tag' => 'added_tag_1',
'value' => 'added_value_1'
],
[
'tag' => 'old_tag_2',
'value' => 'old_value_2'
],
[
'tag' => 'old_tag_3',
'value' => 'old_value_3'
]
]
]
]
],
[
[
'names' => [
'1_Item_Tags_replace',
'2_Item_Tags_replace'
],
'Tags' => [
'action' => 'Replace',
'tags' => []
],
'expected_tags' => [
'1_Item_Tags_replace' => [
[
'tag' => '',
'value' => ''
]
],
'2_Item_Tags_replace' => [
[
'tag' => '',
'value' => ''
]
]
]
]
],
[
[
'names' => [
'1_Item_Tags_replace',
'2_Item_Tags_replace'
],
'Tags' => [
'action' => 'Replace',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'replaced_tag',
'value' => 'replaced_value'
]
]
],
'expected_tags' => [
'1_Item_Tags_replace' => [
[
'tag' => 'replaced_tag',
'value' => 'replaced_value'
]
],
'2_Item_Tags_replace' => [
[
'tag' => 'replaced_tag',
'value' => 'replaced_value'
]
]
]
]
],
[
[
'names' => [
'1_Item_Tags_remove',
'2_Item_Tags_remove'
],
'Tags' => [
'action' => 'Remove',
'tags' => [
[
'tag' => '',
'value' => ''
]
]
],
'expected_tags' => [
'1_Item_Tags_remove' => [
[
'tag' => 'remove_tag_1',
'value' => 'remove_value_1'
],
[
'tag' => 'remove_tag_2',
'value' => 'remove_value_2'
]
],
'2_Item_Tags_remove' => [
[
'tag' => 'remove_tag_2',
'value' => 'remove_value_2'
]
]
]
]
],
[
[
'names' => [
'1_Item_Tags_remove',
'2_Item_Tags_remove',
'3_Item_Tags_remove'
],
'Tags' => [
'action' => 'Remove',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'remove_tag_2',
'value' => 'remove_value_2'
]
]
],
'expected_tags' => [
'1_Item_Tags_remove' => [
[
'tag' => 'remove_tag_1',
'value' => 'remove_value_1'
]
],
'2_Item_Tags_remove' => [
[
'tag' => '',
'value' => ''
]
],
'3_Item_Tags_remove' => [
[
'tag' => 'remove_tag_3',
'value' => 'remove_value_3'
]
]
]
]
],
// Different symbols in tag names and values.
[
[
'names' => [
'1_Item_No_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Add',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => '!@#$%^&*()_+<>,.\/',
'value' => '!@#$%^&*()_+<>,.\/'
],
[
'tag' => 'tag1',
'value' => 'value1'
],
[
'tag' => 'tag2'
],
[
'tag' => '{$MACRO:A}',
'value' => '{$MACRO:A}'
],
[
'tag' => '{$MACRO}',
'value' => '{$MACRO}'
],
[
'tag' => 'Таг',
'value' => 'Значение'
]
]
]
]
],
// Two tags with equal tag names.
[
[
'names' => [
'1_Item_No_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Replace',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'tag3',
'value' => '3'
],
[
'tag' => 'tag3',
'value' => '4'
]
]
]
]
],
// Two tags with equal tag values.
[
[
'names' => [
'1_Item_No_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Replace',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'tag4',
'value' => '5'
],
[
'tag' => 'tag5',
'value' => '5'
]
]
]
]
],
// Tag with trailing spaces.
[
[
'names' => [
'1_Item_No_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Replace',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => ' trimmed tag ',
'value' => ' trimmed value '
]
]
],
'trim' => true
]
],
// Tag with long name and value.
[
[
'names' => [
'1_Item_No_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
],
'Tags' => [
'action' => 'Replace',
'tags' => [
[
'action' => USER_ACTION_UPDATE,
'index' => 0,
'tag' => 'Long tag name. Long tag name. Long tag name. Long tag name. Long tag name.'.
' Long tag name. Long tag name. Long tag name.',
'value' => 'Long tag value. Long tag value. Long tag value. Long tag value. Long tag value.'.
' Long tag value. Long tag value. Long tag value. Long tag value.'
]
]
]
]
]
];
}
/**
* Mass update of items or item prototypes tags.
*
* @param array $data data provider
* @param boolean $prototypes true if item prototype, false if item
*/
public function executeItemsTagsMassUpdate($data, $prototypes = false) {
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
$old_hash = CDBHelper::getHash('SELECT * FROM items ORDER BY itemid');
}
$dialog = $this->openMassUpdateForm($prototypes, $data['names']);
$form = $dialog->asForm();
$form->selectTab('Tags');
$form->getLabel('Tags')->click();
$form->query('id:mass_update_tags')->asSegmentedRadio()->one()->fill($data['Tags']['action']);
if ($data['Tags']['tags'] !== []) {
$this->query('class:tags-table')->asMultifieldTable()->one()->fill($data['Tags']['tags']);
}
$dialog->query('button:Update')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
$error = $prototypes ? 'Cannot update item prototypes' : 'Cannot update items';
$this->assertMessage(TEST_BAD, $error, $data['details']);
$this->assertEquals($old_hash, CDBHelper::getHash('SELECT * FROM items ORDER BY itemid'));
}
else {
$this->assertMessage(TEST_GOOD, ($prototypes ? 'Item prototypes updated' : 'Items updated'));
// Check changed fields in saved item form.
foreach ($data['names'] as $name) {
$table = $this->query('xpath://form[@name="items"]/table[@class="list-table"]')->asTable()->one();
$table->query('link', $name)->one()->waitUntilClickable()->click();
$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
$form->selectTab('Tags');
$expected = $data['Tags']['tags'];
if (!array_key_exists('expected_tags', $data)) {
// Remove action and index fields for asserting expected result.
foreach ($expected as &$tag) {
unset($tag['action'], $tag['index']);
if (CTestArrayHelper::get($data, 'trim', false) === false) {
continue;
}
// Remove trailing spaces from tag and value for asserting expected result.
foreach ($expected as $i => &$options) {
foreach (['tag', 'value'] as $parameter) {
if (array_key_exists($parameter, $options)) {
$options[$parameter] = trim($options[$parameter]);
}
}
}
unset($options);
}
unset($tag);
}
$expected_tags = array_key_exists('expected_tags', $data) ? $data['expected_tags'][$name] : $expected;
$this->query('class:tags-table')->asMultifieldTable()->one()->checkValue($expected_tags);
$form->query('button:Cancel')->one()->waitUntilClickable()->click();
$this->page->waitUntilReady();
}
}
}
/**
* Cancel Mass updating of items or item prototypes.
*
* @param boolean $prototypes true if item prototype, false if item
*/
public function executeMassUpdateCancel($prototypes = false) {
$old_hash = CDBHelper::getHash('SELECT * FROM items ORDER BY itemid');
$items = [
'1_Item_Tags_Preprocessing',
'2_Item_Tags_Preprocessing',
'1_Item_No_Tags_Preprocessing',
'2_Item_No_Tags_Preprocessing'
];
$dialog = $this->openMassUpdateForm($prototypes, $items);
$dialog->query('button:Cancel')->one()->waitUntilClickable()->click();
// Check that UI returned to previous page and hash remained unchanged.
$this->page->waitUntilReady();
$this->page->assertHeader($prototypes ? 'Item prototypes' : 'Items');
$this->assertEquals($old_hash, CDBHelper::getHash('SELECT * FROM items ORDER BY itemid'));
}
/**
* Select items or item prototypes in list and open Mass update form.
*
* @param boolean $prototypes true if item prototype, false if item
* @param array $data items to be mass updated
*
* @return CElement
*/
private function openMassUpdateForm($prototypes, $data) {
$link = ($prototypes)
? 'disc_prototypes.php?parent_discoveryid='.self::RULEID.'&context=host'
: 'items.php?filter_set=1&filter_hostids%5B0%5D='.self::HOSTID.'&context=host';
$this->page->login()->open($link);
// Get item table.
$table = $this->query('xpath://form[@name="items"]/table[@class="list-table"]')->asTable()->one();
$table->findRows('Name', $data)->select();
// Open mass update form.
$this->query('button:Mass update')->one()->click();
return COverlayDialogElement::find()->one()->waitUntilReady();
}
}