<?php
/*
** Copyright (C) 2001-2025 Zabbix SIA
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** 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 Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see <https://www.gnu.org/licenses/>.
**/


require_once dirname(__FILE__).'/../../include/CLegacyWebTest.php';
require_once dirname(__FILE__).'/../../../include/items.inc.php';
require_once dirname(__FILE__).'/../../../include/classes/api/services/CItemGeneral.php';
require_once dirname(__FILE__).'/../../../include/classes/api/services/CItem.php';
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';

use Facebook\WebDriver\WebDriverBy;

/**
 * @backup items
 * TODO: The following annotation (ignoreBrowserErrors) is added to ignore JS errors generated by information type
 *       dropdown field when "on change" event is fired before "on focus" event is fired.
 * @ignoreBrowserErrors
 */
class testFormItem extends CLegacyWebTest {

	/**
	 * Attach MessageBehavior to the test.
	 */
	public function getBehaviors() {
		return [CMessageBehavior::class];
	}

	/**
	 * The name of the test host created in the test data set.
	 *
	 * @var string
	 */
	protected $host = 'Simple form test host';

	/**
	 * The name of the item created in the test data set.
	 *
	 * @var string
	 */
	protected $item = 'testFormItem1';

	// Returns layout data
	public static function layout() {
		return [
			[
				['type' => 'Zabbix agent', 'host' => 'Simple form test host']
			],
			[
				['host' => 'Simple form test host', 'key' => 'test-item-form1']
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Numeric (float)', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Character', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Log', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Text', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent (active)', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Simple check', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Numeric (float)', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Character', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Log', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Text', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SNMP trap', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix internal', 'host' => 'Simple form test host'	]
			],
			[
				[
					'type' => 'Zabbix internal',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				['type' => 'Zabbix trapper', 'host' => 'Simple form test host']
			],
			[
				['type' => 'External check', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Database monitor', 'host' => 'Simple form test host']
			],
			[
				['type' => 'IPMI agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SSH agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Public key', 'host' => 'Simple form test host']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Password', 'host' => 'Simple form test host']
			],
			[
				[
					'type' => 'SSH agent',
					'value_type' => 'Numeric (unsigned)',
					'host' => 'Simple form test host'
				]
			],
			[
				[
					'type' => 'SSH agent',
					'authtype' => 'Password',
					'value_type' => 'Character',
					'host' => 'Simple form test host'
				]
			],
			[
				['type' => 'TELNET agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'JMX agent', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Calculated', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Script', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Browser', 'host' => 'Simple form test host']
			],
			[
				['type' => 'Zabbix agent', 'template' => 'Inheritance test template']
			],
			[
				[
					'type' => 'Zabbix agent',
					'template' => 'Inheritance test template',
					'key' => 'test-inheritance-item1'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'host' => 'Template inheritance test host',
					'key' => 'test-inheritance-item1'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Numeric (float)',
					'template' => 'Inheritance test template'
					]
			],
			[
				[
					'type' => 'Zabbix agent',
					'value_type' => 'Character',
					'template' => 'Inheritance test template'
				]
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Log', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Zabbix agent', 'value_type' => 'Text', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Zabbix agent (active)', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Simple check', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Numeric (float)', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Character', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP agent', 'value_type' => 'Text', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SNMP trap', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Zabbix internal', 'template' => 'Inheritance test template']
			],
			[
				[
					'type' => 'Zabbix internal',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'Zabbix internal',
					'template' => 'Inheritance test template',
					'key' => 'test-inheritance-item1'
				]
			],
			[
				['type' => 'Zabbix trapper', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'External check', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Database monitor', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'IPMI agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SSH agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Public key', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'SSH agent', 'authtype' => 'Password', 'template' => 'Inheritance test template']
			],
			[
				[
					'type' => 'SSH agent',
					'value_type' => 'Numeric (unsigned)',
					'template' => 'Inheritance test template'
				]
			],
			[
				[
					'type' => 'SSH agent',
					'authtype' => 'Password',
					'value_type' => 'Character',
					'template' => 'Inheritance test template'
				]
			],
			[
				['type' => 'TELNET agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'JMX agent', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Calculated', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Script', 'template' => 'Inheritance test template']
			],
			[
				['type' => 'Browser', 'template' => 'Inheritance test template']
			],
			[
				[
					'host' => 'Template inheritance test host',
					'hostTemplate' => 'Inheritance test template',
					'key' => 'test-inheritance-item-preprocessing',
					'preprocessing' => true
				]
			],
			[
				['type' => 'Dependent item', 'value_type' => 'Numeric (unsigned)', 'host' => 'Simple form test host']
			]
		];
	}

	/**
	 * @dataProvider layout
	 */
	public function testFormItem_CheckLayout($data) {
		$context = array_key_exists('host', $data) ? 'host' : 'template';
		$host_name = array_key_exists('host', $data) ? $data['host'] : $data['template'];

		$dbResult = DBselect('SELECT hostid,status FROM hosts WHERE host='.zbx_dbstr($host_name));
		$host_info = DBfetch($dbResult);

		$this->assertNotEquals($host_info, null);

		$hostid = $host_info['hostid'];
		$status = $host_info['status'];

		if (isset($data['key'])) {
			$dbResult = DBselect(
				'SELECT itemid,templateid'.
				' FROM items'.
				' WHERE hostid='.$hostid.
					' AND key_='.zbx_dbstr($data['key'])
			);
			$template_info = DBfetch($dbResult);

			$this->assertNotEquals($template_info, null);

			$itemid = $template_info['itemid'];
			if (0 != $template_info['templateid'])
				$templateid = $template_info['templateid'];
		}

		$this->page->login()->open('zabbix.php?action=item.list&filter_set=1&filter_hostids%5B0%5D='.$hostid.'&context='.$context);
		$this->page->assertTitle('Configuration of items');
		$this->page->assertHeader('Items');

		$this->query(isset($itemid)
			? 'link:'.CDBHelper::getValue('SELECT name from items WHERE itemid='.$itemid)
			: 'button:Create item'
		)->one()->click();

		$dialog = COverlayDialogElement::find()->one()->waitUntilReady();
		$this->page->assertTitle('Configuration of items');
		$this->assertEquals(isset($itemid) ? 'Item' : 'New item', $dialog->getTitle());
		$form = $dialog->asForm();
		$dialog_footer = $dialog->getFooter();

		if (isset($templateid)) {
			$this->zbxTestTextPresent('Parent items');
			if (isset($data['hostTemplate'])) {
				$this->assertTrue($form->query('link', $data['hostTemplate'])->exists());
			}
		}
		else {
			$this->zbxTestTextNotPresent('Parent items');
		}

		$this->assertTrue($form->getField('Name')->isDisplayed());
		$this->assertEquals(255, $form->getField('Name')->getAttribute('maxlength'));
		$this->assertEquals('true', $form->getField('Name')->getAttribute('autofocus'));

		if (isset($templateid)) {
			$this->assertEquals('true', $form->getField('Name')->getAttribute('readonly'));
		}

		$this->assertTrue($form->getField('Type')->isDisplayed());
		$type_field = $form->getField('Type')->asDropdown();

		if (!isset($templateid)) {
			$options = $type_field->getOptions()->asText();
			$this->assertEquals($options, [
				'Zabbix agent',
				'Zabbix agent (active)',
				'Simple check',
				'SNMP agent',
				'SNMP trap',
				'Zabbix internal',
				'Zabbix trapper',
				'External check',
				'Database monitor',
				'HTTP agent',
				'IPMI agent',
				'SSH agent',
				'TELNET agent',
				'JMX agent',
				'Calculated',
				'Dependent item',
				'Script',
				'Browser'
			]);
			if (isset($data['type'])) {
				$type_field->select($data['type']);
				$type = $data['type'];
			}
			else {
				$type = $type_field->getText();
			}
		}
		else {
			$this->assertEquals('true', $form->getField('Type')->getAttribute('readonly'));
			$type = $type_field->getText();
		}

		$this->assertTrue($form->getField('Key')->isDisplayed());
		$this->assertEquals(2048, $form->getField('Key')->getAttribute('maxlength'));

		if (!isset($templateid)) {
			$this->assertTrue($form->query('xpath://button[@class="js-select-key btn-grey"]')->one()->isDisplayed());
		}
		else {
			$this->assertEquals('true', $form->getField('Key')->getAttribute('readonly'));
		}

		if ($type == 'Database monitor' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', 'db.odbc.select[<unique short description>,<dsn>,<connection string>]');
		}

		if ($type == 'SSH agent' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', 'ssh.run[<unique short description>,<ip>,<port>,<encoding>,<ssh options>,<subsystem>]');
		}

		if ($type == 'TELNET agent' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', 'telnet.run[<unique short description>,<ip>,<port>,<encoding>]');
		}

		if ($type == 'JMX agent' && !isset($itemid)) {
			$this->zbxTestAssertElementValue('key', '');
			$this->assertTrue($dialog->query('button:Select')->one()->isEnabled());
		}

		if (isset($templateid)) {
			$value_type = $form->getField('Type of information')->asDropdown()->getText();
		}
		elseif (isset($data['value_type'])) {
			$form->getField('Type of information')->asDropdown()->select($data['value_type']);
			$value_type = $data['value_type'];
		}
		else {
			$value_type = $form->getField('Type of information')->asDropdown()->getText();
		}

		if ($type == 'SSH agent') {
			if (isset($data['authtype'])) {
				$form->getField('Authentication method')->asDropdown()->select($data['authtype']);
				$authtype = $data['authtype'];
			}
			else {
				$authtype = $form->getField('Authentication method')->asDropdown()->getText();
			}
		}

		if ($type == 'Database monitor') {
			$this->assertTrue($form->getField('SQL query')->isDisplayed());
			$this->assertEquals(7, $form->getField('SQL query')->getAttribute('rows'));
			$this->zbxTestAssertElementValue('params_ap', '');
		}
		else {
			$this->assertFalse($form->query('id:js-item-sql-query-label')->one()->isDisplayed());
			$this->assertFalse($form->query('id:params_ap')->one()->isDisplayed());
		}

		if ($type == 'SSH agent' || $type == 'TELNET agent' ) {
			$this->assertTrue($form->getField('Executed script')->isDisplayed());
			$this->assertEquals(7, $form->getField('Executed script')->getAttribute('rows'));
		}
		else {
			$this->assertFalse($form->query('id:js-item-executed-script-label')->one()->isDisplayed());
			$this->assertFalse($form->query('id:params_es')->one()->isDisplayed());
		}

		if ($type == 'Calculated') {
			$this->assertTrue($form->getField('Formula')->isDisplayed());
			$this->assertEquals(7, $form->getField('Formula')->getAttribute('rows'));
		}
		else {
			$this->assertFalse($form->query('id:js-item-formula-label')->one()->isDisplayed());
			$this->assertFalse($form->query('id:params_f')->one()->isDisplayed());
		}

		if ($status != HOST_STATUS_TEMPLATE) {
			$interfaceType = itemTypeInterface($this->zbxTestGetValue('//*[@id="type"]'));
			switch ($interfaceType) {
				case INTERFACE_TYPE_AGENT :
				case INTERFACE_TYPE_SNMP :
				case INTERFACE_TYPE_JMX :
				case INTERFACE_TYPE_IPMI :
				case INTERFACE_TYPE_ANY :
				case INTERFACE_TYPE_OPT :
					$this->assertTrue($form->query('id:js-item-interface-label')->one()->isDisplayed());
					$dbInterfaces = DBfetchArray(DBselect(
						'SELECT type,ip,port'.
						' FROM interface'.
						' WHERE hostid='.$hostid.
							(($interfaceType == INTERFACE_TYPE_ANY || $interfaceType === INTERFACE_TYPE_OPT) ? '' : ' AND type='.$interfaceType)
					));
					if ($dbInterfaces != null) {
						foreach ($dbInterfaces as $host_interface) {
							$this->zbxTestAssertElementPresentXpath('//z-select[@id="interface-select"]//li[text()="'.
									$host_interface['ip'].':'.$host_interface['port'].'"]');
						}
					}
					else {
						$this->zbxTestTextPresent('No interface found');
						$this->assertFalse($form->query('id:interface-select')->one()->isDisplayed());
					}
					break;
				default:
					$this->zbxTestTextNotVisible(['Host interface', 'No interface found']);
					$this->assertFalse($form->query('id:interface-select')->one()->isDisplayed());
					break;
			}
		}

		if ($type == 'IPMI agent') {
			$this->assertTrue($form->getField('IPMI sensor')->isDisplayed());
			$this->assertEquals(128, $form->getField('IPMI sensor')->getAttribute('maxlength'));
		}
		else {
			$this->zbxTestTextNotVisible('IPMI sensor');
			$this->assertFalse($form->getField('IPMI sensor')->isDisplayed());
		}

		if ($type == 'SSH agent') {
			$this->assertTrue($form->query('id:authtype')->one()->isDisplayed());
			$this->assertEquals(['Password', 'Public key'], $form->getField('Authentication method')->asDropdown()
					->getOptions()->asText()
			);
		}
		else {
			$this->assertFalse($form->query('id:authtype')->one()->isDisplayed());
			$this->assertFalse($form->query('id:js-item-authtype-label')->one()->isDisplayed());
		}

		if ($type == 'SSH agent' || $type == 'TELNET agent' || $type == 'JMX agent' || $type == 'Simple check'
				|| $type == 'Database monitor') {
			$this->assertTrue($form->getField('User name')->isDisplayed());
			$this->assertEquals(255, $form->getField('User name')->getAttribute('maxlength'));

			if (isset($authtype) && $authtype == 'Public key') {
				$this->assertTrue($form->getField('Key passphrase')->isDisplayed());
				$this->assertEquals(255, $form->getField('Key passphrase')->getAttribute('maxlength'));
				$this->assertFalse($form->query('name:password')->one()->isDisplayed());
			}
			else {
				$this->assertTrue($form->getField('Password')->isDisplayed());
				$this->assertEquals(255, $form->getField('Password')->getAttribute('maxlength'));
			}
		}
		else {
			$this->assertFalse($form->query('id', ['username', 'password'])->one()->isDisplayed());
		}

		if	(isset($authtype) && $authtype == 'Public key') {
			$this->assertTrue($form->query('id', ['publickey', 'privatekey'])->one()->isDisplayed());
			$this->assertEquals(64, $form->getField('Public key file')->getAttribute('maxlength'));
			$this->assertEquals(64, $form->getField('Private key file')->getAttribute('maxlength'));
		}
		else {
			$this->assertFalse($form->query('id', ['publickey', 'privatekey'])->one()->isDisplayed());
		}

		if	($type === 'SNMP agent') {
			$this->assertTrue($form->getField('SNMP OID')->isDisplayed());
			$this->assertEquals(512, $form->getField('SNMP OID')->getAttribute('maxlength'));
			if (!isset($itemid)) {
				$this->assertEquals('walk[OID1,OID2,...]', $form->getField('SNMP OID')->getAttribute('placeholder'));
			}

			//Check hintbox.
			$hint_text = "Field requirements:".
				"\nwalk[OID1,OID2,...] - to retrieve a subtree".
				"\nget[OID] - to retrieve a single value".
				"\nOID - (legacy) to retrieve a single value synchronously, optionally combined with other values";

			$form->getLabel('SNMP OID')->query('xpath:./button[@data-hintbox]')->one()->click();
			$hint = $this->query('xpath://div[@data-hintboxid]')->waitUntilPresent();
			$this->assertEquals($hint_text, $hint->one()->getText());
			$hint->one()->query('xpath:.//button[@class="btn-overlay-close"]')->one()->click();
			$hint->waitUntilNotPresent();
		}
		else {
			$this->assertFalse($form->getField('SNMP OID')->isDisplayed());
		}

		if (in_array($type, ['Script', 'Browser'])) {
			// Check parameters table layout.
			$parameters_table = $form->getField('Parameters')->asTable();
			$this->assertSame(['Name', 'Value', ''], $parameters_table->getHeadersText());

			$this->assertEquals(['Remove', 'Add'], $parameters_table->query('tag:button')->all()
					->filter(CElementFilter::CLICKABLE)->asText()
			);

			foreach(['parameters[0][name]' => 255, 'parameters[0][value]' => 2048] as $input_name => $maxlength) {
				$input = $parameters_table->query('name', $input_name)->one();
				$this->assertEquals($maxlength, $input->getAttribute('maxlength'));
				$this->assertEquals('', $input->getValue());
			}

			// Check Script field.
			$script_values = [
				'Script' => '',
				'Browser' => "var browser = new Browser(Browser.chromeOptions());\n\n".
						"try {\n".
						" browser.navigate(\"https://example.com\");\n".
						" browser.collectPerfEntries();\n".
						"}\n".
						"finally {\n".
						" return JSON.stringify(browser.getResult());\n".
						"}"
			];

			$this->assertTrue($form->isRequired('Script'));
			$script_field = $form->getField('Script');
			$this->assertEquals('script', $script_field->query('xpath:.//input[@type="text"]')->one()
					->getAttribute('placeholder')
			);

			$script_dialog = $script_field->edit();
			$this->assertEquals('JavaScript', $script_dialog->getTitle());
			$script_input = $script_dialog->query('xpath:.//textarea')->one();

			foreach (['placeholder' => 'return value', 'maxlength' => 65535] as $attribute => $value) {
				$this->assertEquals($value, $script_input->getAttribute($attribute));
			}
			$this->assertEquals($script_values[$type], $script_input->getText());
			$script_dialog->close();
		}

		switch ($type) {
			case 'Zabbix agent':
			case 'Zabbix agent (active)':
			case 'Simple check':
			case 'SNMP agent':
			case 'Zabbix internal':
			case 'External check':
			case 'Database monitor':
			case 'IPMI agent':
			case 'SSH agent':
			case 'TELNET agent':
			case 'JMX agent':
			case 'Calculated':
			case 'Script':
			case 'Browser':
				$this->assertTrue($form->getField('Update interval')->isDisplayed());
				$this->assertEquals(255, $form->getField('Update interval')->getAttribute('maxlength'));
				if (!isset($itemid)) {
					$form->checkValue(['Update interval' => '1m']);
				}
				break;
			default:
				$this->assertFalse($form->getField('Update interval')->isDisplayed());
		}

		$value_types = ($type === 'Dependent item')
			? ['Numeric (unsigned)', 'Numeric (float)', 'Character', 'Log', 'Text', 'Binary']
			: ['Numeric (unsigned)', 'Numeric (float)', 'Character', 'Log', 'Text'];

		if (isset($templateid)) {
			$this->assertEquals('true', $form->getField('Type of information')->getAttribute('readonly'));
		}
		else {
			$this->assertEquals($value_types, $form->getField('Type of information')->asDropdown()->getOptions()->asText());

			foreach (['Numeric (unsigned)', 'Numeric (float)', 'Character', 'Log', 'Text'] as $info_type) {
				$this->zbxTestIsEnabled('//*[@id="value_type"]//li[text()='.CXPathHelper::escapeQuotes($info_type).']');
			}
		}

		if ($value_type === 'Numeric (float)' || ($value_type == 'Numeric (unsigned)')) {
			$this->assertTrue($form->getField('Units')->isDisplayed());
			$this->assertEquals(255, $form->getField('Units')->getAttribute('maxlength'));
			if(isset($templateid)) {
				$this->assertEquals('true', $form->getField('Units')->getAttribute('readonly'));
			}
		}
		else {
			$this->assertFalse($form->getField('Units')->isDisplayed());
		}

		// Custom intervals field isn't visible for some item types.
		if (in_array($type, ['SNMP trap', 'Zabbix trapper', 'Dependent item'])) {
			$this->assertFalse($form->getField('Custom intervals')->isDisplayed());
			$this->assertFalse($form->query("xpath://div[@id='js-item-flex-intervals-field']//button[@class='btn-link element-table-add']")
					->one()->isDisplayed());
		}
		else {
			$this->zbxTestTextPresent(['Custom intervals', 'Interval',  'Period', 'Action']);
			$this->assertTrue($form->getField('Custom intervals')->isDisplayed());
			$this->zbxTestTextPresent(['Flexible', 'Scheduling', 'Update interval']);
			$this->assertEquals(255, $form->getField('id:delay_flex_0_delay')->getAttribute('maxlength'));
			$this->assertEquals('50s', $form->getField('id:delay_flex_0_delay')->getAttribute('placeholder'));

			$this->assertEquals(255, $form->getField('id:delay_flex_0_period')->getAttribute('maxlength'));
			$this->assertEquals('1-7,00:00-24:00', $form->getField('id:delay_flex_0_period')
					->getAttribute('placeholder')
			);

			$this->assertTrue($form->query("xpath://div[@id='js-item-flex-intervals-field']//button[@class='btn-link element-table-add']")
					->one()->isClickable()
			);
		}

		$this->assertTrue($form->getField('History')->isDisplayed());
		$this->assertEquals(255, $form->getField('History')->getAttribute('maxlength'));

		if (!isset($itemid)) {
			$this->zbxTestAssertElementValue('history', '31d');
		}

		if ($value_type == 'Numeric (unsigned)' || $value_type == 'Numeric (float)') {
			$this->assertTrue($form->getField('Trends')->isDisplayed());
			$this->assertEquals(255, $form->getField('Trends')->getAttribute('maxlength'));
			if (!isset($itemid)) {
				$this->assertEquals('365d', $form->getField('Trends')->getValue());
			}
		}
		else {
			$this->assertFalse($form->getField('Trends')->isDisplayed());
		}

		if ($value_type == 'Numeric (float)' || $value_type == 'Numeric (unsigned)' || $value_type == 'Character') {
			$this->zbxTestTextPresent('Value mapping');
			$valuemap_field = $form->getField('Value mapping');
			$this->assertTrue($valuemap_field->isDisplayed());
			if (!isset($templateid)) {
				$this->assertEquals('', $valuemap_field->getValue());

				$db_valuemap = [];
				$valuemap_result = DBselect('SELECT name FROM valuemap WHERE hostid='.$host_info['hostid']);
				while ($row = DBfetch($valuemap_result)) {
					$db_valuemap[] = $row['name'];
				}
				$db_mappings = CDBHelper::getAll('SELECT vm.name, m.sortorder, m.value, m.newvalue FROM valuemap vm INNER JOIN'.
						' valuemap_mapping m ON m.valuemapid = vm.valuemapid WHERE vm.hostid='.$host_info['hostid'].
						' ORDER BY vm.name, m.sortorder');

				$valuemap_field->edit();
				$valuemap_overlay = COverlayDialogElement::find()->all()->last()->waitUntilReady();
				if ($db_valuemap !== []) {
					$this->assertEquals('Value mapping', $valuemap_overlay->getTitle());
					$valuemap_table = $valuemap_overlay->query('class:list-table')->one()->asTable();
					$this->assertEquals(['Name', 'Mapping'], $valuemap_table->getHeadersText());

					$expected_count = (count($db_valuemap) > 3) ? 3 : count($db_valuemap);
					$table_rows = $valuemap_table->getRows();
					$this->assertEquals($expected_count, $table_rows->count());
					foreach($table_rows as $value_mapping) {
						$valuemap_name = ltrim($value_mapping->getColumn('Name')->getText(), $host_name.': ');
						$this->assertTrue(in_array($valuemap_name, $db_valuemap));

						$mappings = [];
						$i = 0;
						foreach ($db_mappings as $db_mapping) {
							if ($db_mapping['name'] === $valuemap_name) {
								if ($i < 3) {
									$mappings[] = '='.$db_mapping['value'].' ⇒ '.$db_mapping['newvalue'];
									$i++;
								}
								else {
									$mappings[] = '…';

									break;
								}
							}
						}
						// Transform newlines in value map table text.
						$source = $value_mapping->getColumn('Mapping')->getText();
						$text = rtrim(preg_replace("/(.*)\n⇒\n(.*)\n?/", "\\1 ⇒ \\2\n", $source), "\n");
						$this->assertEquals(implode("\n", $mappings), $text);
					}
				}
				else {
					$this->assertEquals('No data found', $valuemap_overlay->query('class:nothing-to-show')->one()->getText());
				}
				$valuemap_overlay->getFooter()->query('button:Cancel')->one()->click();
			}
			else {
				$this->assertTrue($valuemap_field->isValid());
				$this->assertFalse($valuemap_field->isEnabled());
			}
		}
		else {
			$this->assertFalse($form->getField('Value mapping')->isDisplayed());
		}

		if ($type == 'Zabbix trapper') {
			$this->assertTrue($form->getField('Allowed hosts')->isDisplayed());
			$this->assertEquals(255, $form->getField('Allowed hosts')->getAttribute('maxlength'));
		}
		else {
			$this->assertFalse($form->getField('Allowed hosts')->isDisplayed());
		}

		if ($value_type == 'Log') {
			$this->assertTrue($form->getField('Log time format')->isDisplayed());
			$this->assertEquals(64, $form->getField('Log time format')->getAttribute('maxlength'));
		}
		else {
			$this->assertFalse($form->getField('Log time format')->isDisplayed());
		}

		$this->zbxTestTextNotPresent(['Applications', 'New application']);

		if ($value_type != 'Log') {
			$this->zbxTestTextPresent('Populates host inventory field');
			$host_inventory = $form->getField('Populates host inventory field')->asDropdown();
			$this->assertEquals($host_inventory->getOptions()->asText(), [
					'-None-',
					'Type',
					'Type (Full details)',
					'Name',
					'Alias',
					'OS',
					'OS (Full details)',
					'OS (Short)',
					'Serial number A',
					'Serial number B',
					'Tag',
					'Asset tag',
					'MAC address A',
					'MAC address B',
					'Hardware',
					'Hardware (Full details)',
					'Software',
					'Software (Full details)',
					'Software application A',
					'Software application B',
					'Software application C',
					'Software application D',
					'Software application E',
					'Contact',
					'Location',
					'Location latitude',
					'Location longitude',
					'Notes',
					'Chassis',
					'Model',
					'HW architecture',
					'Vendor',
					'Contract number',
					'Installer name',
					'Deployment status',
					'URL A',
					'URL B',
					'URL C',
					'Host networks',
					'Host subnet mask',
					'Host router',
					'OOB IP address',
					'OOB subnet mask',
					'OOB router',
					'Date HW purchased',
					'Date HW installed',
					'Date HW maintenance expires',
					'Date HW decommissioned',
					'Site address A',
					'Site address B',
					'Site address C',
					'Site city',
					'Site state / province',
					'Site country',
					'Site ZIP / postal',
					'Site rack location',
					'Site notes',
					'Primary POC name',
					'Primary POC email',
					'Primary POC phone A',
					'Primary POC phone B',
					'Primary POC cell',
					'Primary POC screen name',
					'Primary POC notes',
					'Secondary POC name',
					'Secondary POC email',
					'Secondary POC phone A',
					'Secondary POC phone B',
					'Secondary POC cell',
					'Secondary POC screen name',
					'Secondary POC notes'
				]);
			$this->assertEquals('-None-', $host_inventory->getText());
		}

		$this->assertTrue($form->getField('Description')->isDisplayed());
		$this->assertEquals(7, $form->getField('Description')->getAttribute('rows'));
		$this->assertTrue($form->getField('Enabled')->asCheckbox()->isSelected());
		$this->assertEquals('Cancel', $dialog_footer->query('button:Cancel')->one()->getText());

		if (isset($itemid)) {
			$this->assertTrue($dialog_footer->query('button:Clone')->one()->isClickable());
		}
		else {
			$this->assertEquals(0, $dialog_footer->query('button:Clone')->all()->filter(CElementFilter::CLICKABLE)
					->count()
			);
		}

		if (isset($itemid) && $status != HOST_STATUS_TEMPLATE) {
			$this->assertTrue($dialog_footer->query('button:Clear history and trends')->one()->isClickable());
		}
		else {
			$this->assertEquals(0, $dialog_footer->query('button:Clear history and trends')->all()
					->filter(CElementFilter::CLICKABLE)->count()
			);
		}

		if ((isset($itemid) && !isset($templateid))) {
			$this->assertTrue($dialog_footer->query('button:Delete')->one()->isClickable());
			$this->assertTrue($dialog_footer->query('button:Update')->one()->isClickable());
		}
		elseif (isset($templateid)) {
			$this->assertFalse($dialog_footer->query('button:Delete')->one()->isEnabled());
		}
		else {
			$this->assertEquals(0, $dialog_footer->query('button:Delete')->all()->filter(CElementFilter::CLICKABLE)
					->count()
			);
		}

		if (isset($templateid) && array_key_exists('preprocessing', $data)) {
			$form->selectTab('Preprocessing');
			$dbResult = DBselect('SELECT * FROM item_preproc WHERE itemid='.$itemid);
			$itemsPreproc = DBfetchArray($dbResult);
			foreach ($itemsPreproc as $itemPreproc) {
				// The array of allowed types must be synced with CItem::SUPPORTED_PREPROCESSING_TYPES.
				$preprocessing_type = get_preprocessing_types($itemPreproc['type'], false,
					CItem::SUPPORTED_PREPROCESSING_TYPES
				);
				$this->zbxTestAssertAttribute("//z-select[@id='preprocessing_".($itemPreproc['step']-1)."_type']", 'readonly');
				$this->zbxTestDropdownAssertSelected("preprocessing_".($itemPreproc['step']-1)."_type", $preprocessing_type);
				if ((1 <= $itemPreproc['type']) && ($itemPreproc['type'] <= 4)) {
					$this->zbxTestAssertAttribute("//input[@id='preprocessing_".($itemPreproc['step']-1)."_params_0']", 'readonly');
					$this->zbxTestAssertElementValue("preprocessing_".($itemPreproc['step']-1)."_params_0", $itemPreproc['params']);
				}
				elseif ($itemPreproc['type'] == 5) {
					$reg_exp = preg_split("/\n/", $itemPreproc['params']);
					$this->zbxTestAssertAttribute("//input[@id='preprocessing_".($itemPreproc['step']-1)."_params_0']", 'readonly');
					$this->zbxTestAssertAttribute("//input[@id='preprocessing_".($itemPreproc['step']-1)."_params_1']", 'readonly');
					$this->zbxTestAssertElementValue("preprocessing_".($itemPreproc['step']-1)."_params_0", $reg_exp[0]);
					$this->zbxTestAssertElementValue("preprocessing_".($itemPreproc['step']-1)."_params_1", $reg_exp[1]);
				}
			}
		}

		$dialog->close();
	}

	// Returns update data
	public static function update() {
		return CDBHelper::getDataProvider("SELECT * FROM items WHERE hostid = 40001 AND key_ LIKE 'test-item-form%'");
	}

	/**
	 * @dataProvider update
	 */
	public function testFormItem_SimpleUpdate($data) {
		$name = $data['name'];

		$sqlItems = "SELECT * FROM items ORDER BY itemid";
		$oldHashItems = CDBHelper::getHash($sqlItems);
		// Open hosts page.
		$this->zbxTestLogin(self::HOST_LIST_PAGE);
		// Find filter form and filter necessary host.
		$this->query('name:zbx_filter')->asForm()->waitUntilReady()->one()->fill(['Name' => $this->host]);
		$this->query('button:Apply')->one()->waitUntilClickable()->click();
		// Find Items link in host row and click it.
		$this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $this->host)
				->getColumn('Items')->query('link:Items')->one()->click();
		$this->zbxTestClickLinkTextWait($name);
		COverlayDialogElement::find()->one()->waitUntilReady()->getFooter()->query('button:Update')->one()->click();
		$this->zbxTestCheckTitle('Configuration of items');
		$this->zbxTestWaitUntilMessageTextPresent('msg-good', 'Item updated');
		$this->zbxTestTextPresent($name);
		$this->zbxTestCheckHeader('Items');

		$this->assertEquals($oldHashItems, CDBHelper::getHash($sqlItems));
	}

	// Returns create data
	public static function create() {
		return [
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Checksum of $1',
					'key' => 'vfs.file.cksum[/sbin/shutdown]',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Duplicate item
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Checksum of $1',
					'key' => 'vfs.file.cksum[/sbin/shutdown]',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'An item with key "vfs.file.cksum[/sbin/shutdown]" already exists on'
					]
				]
			],
			// Item name is missing
			[
				[
					'expected' => TEST_BAD,
					'key' =>'item-name-missing',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "name": cannot be empty.'
					]
				]
			],
			// Item key is missing
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item name',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "key": cannot be empty.'
					]
				]
			],
			// Empty timedelay
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item delay',
					'key' => 'item-delay-test',
					'delay' => 0,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": cannot be equal to zero without custom intervals.'
					]
				]
			],
			// Incorrect timedelay
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item delay',
					'key' => 'item-delay-test',
					'delay' => '-30',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "delay": a time unit is expected'
					]
				]
			],
			// Incorrect timedelay
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item delay',
					'key' => 'item-delay-test',
					'delay' => 86401,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": value must be one of 0-86400.'
					]
				]
			],
			// Empty time flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-11,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1-11,00:00-24:00".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-25:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1-7,00:00-25:00".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,24:00-00:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1-7,24:00-00:00".'
					]
				]
			],
			// Incorrect flex period
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00;2,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid interval "1,00:00-24:00;2,00:00-24:00".'
					]
				]
			],
			// Multiple flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-test',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay1',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'delay' => 0,
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": must have at least one interval greater than 0.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex combined with flex periods',
					'key' => 'item-flex-delay2',
					'delay' => 0,
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					],
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay3',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay4',
					'delay' => 0,
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay5',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					],
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/delay": non-active intervals cannot fill the entire time.'
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay6',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '2,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '3,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '4,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '5,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '6,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '7,00:00-24:00', 'remove' => true],
						['flexDelay' => 50, 'flexTime' => '1,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '2,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '3,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '4,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex',
					'key' => 'item-flex-delay7',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-7,00:00-24:00', 'remove' => true],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					]
				]
			],
			// Delay combined with flex periods
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex Check',
					'key' => 'item-flex-delay8',
					'flexPeriod' => [
						['flexDelay' => 0, 'flexTime' => '1-5,00:00-24:00', 'remove' => true],
						['flexDelay' => 0, 'flexTime' => '6-7,00:00-24:00', 'remove' => true],
						['flexDelay' => 50, 'flexTime' => '1-5,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '6-7,00:00-24:00']
					],
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Seven flexfields - save OK
			[
				[
					'expected' => TEST_GOOD,
					'name' => 'Item flex-maximum save OK',
					'key' => 'item-flex-maximum-save',
					'flexPeriod' => [
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00'],
						['flexDelay' => 50, 'flexTime' => '1-7,00:00-24:00']
					],
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-empty',
					'history' => ' ',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/history": cannot be empty'
					]
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-test',
					'history' => 3599,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/history": value must be one of 0, 3600-788400000.'
					]
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-test',
					'history' => 788400001,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/history": value must be one of 0, 3600-788400000.'
					]
				]
			],
			// History
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item history',
					'key' => 'item-history-test',
					'history' => '-1',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/history": value must be one of 0, 3600-788400000.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-empty',
					'trends' => ' ',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/trends": cannot be empty.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-test',
					'trends' => '-1',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/trends": value must be one of 0, 86400-788400000.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-test',
					'trends' => 788400001,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/trends": value must be one of 0, 86400-788400000.'
					]
				]
			],
			// Trends
			[
				[
					'expected' => TEST_BAD,
					'name' => 'Item trends',
					'key' => 'item-trends-test',
					'trends' => 86399,
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/trends": value must be one of 0, 86400-788400000.'
					]
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'name' => '!@#$%^&*()_+-=[]{};:"|,./<>?',
					'key' => 'item-symbols-test',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// List of all item types
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix agent',
					'name' => 'Zabbix agent',
					'key' => 'item-zabbix-agent',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// Update and custom intervals are hidden if item key is mqtt.get
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix agent (active)',
					'name' => 'Zabbix agent (active) mqtt',
					'key' => 'mqtt.get[0]',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix agent (active)',
					'name' => 'Zabbix agent (active)',
					'key' => 'item-zabbix-agent-active',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Simple check',
					'name' => 'Simple check',
					'key' => 'item-simple-check',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'SNMP agent',
					'name' => 'SNMP agent',
					'key' => 'item-snmp-agent',
					'snmp_oid' => '[IF-MIB::]ifInOctets.1',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'SNMP trap',
					'name' => 'SNMP trap',
					'key' => 'snmptrap.fallback',
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix internal',
					'name' => 'Zabbix internal',
					'key' => 'item-zabbix-internal',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix trapper',
					'name' => 'Zabbix trapper',
					'key' => 'item-zabbix-trapper',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix trapper',
					'name' => 'Zabbix trapper with macro in allowed hosts field',
					'key' => 'item-zabbix-trapper-macro',
					'allowed_hosts' => '{$TEST}',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Zabbix trapper',
					'name' => 'Zabbix trapper with macro and ip in allowed hosts field',
					'key' => 'item-zabbix-trapper-macro-ip',
					'allowed_hosts' => '{$MACRO},127.0.0.1',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'External check',
					'name' => 'External check',
					'key' => 'item-external-check',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Database monitor',
					'name' => 'Database monitor',
					'key' => 'item-database-monitor',
					'params_ap' => 'query',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent',
					'key' => 'item-ipmi-agent',
					'ipmi_sensor' => 'ipmi_sensor',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			// IPMI sensor is optional if item key is ipmi.get
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent with ipmi.get',
					'key' => 'ipmi.get',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'SSH agent',
					'name' => 'SSH agent',
					'key' => 'item-ssh-agent',
					'username' => 'zabbix',
					'params_es' => 'executed script',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'TELNET agent',
					'name' => 'TELNET agent',
					'key' => 'item-telnet-agent',
					'username' => 'zabbix',
					'params_es' => 'executed script',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Script',
					'name' => 'Script item',
					'key' => 'script.item',
					'script' => 'zabbix',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Browser',
					'name' => 'Default browser item',
					'key' => 'default.browser.item',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Script',
					'name' => 'Empty script',
					'key' => 'empty.script',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/params": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Browser',
					'name' => 'Browser item - empty script',
					'key' => 'empty.script.browser.item',
					'script' => '',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/params": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Script',
					'name' => 'Empty parameter name - script item',
					'key' => 'empty.parameter.script.item',
					'script' => 'script',
					'params_value' => 'value',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/parameters/1/name": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Browser',
					'name' => 'Empty parameter name - browser item',
					'key' => 'empty.param.name.browser.item',
					'params_value' => 'value',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/parameters/1/name": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent error',
					'key' => 'item-ipmi-agent-error',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/ipmi_sensor": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'IPMI agent',
					'name' => 'IPMI agent with spaces',
					'key' => 'item-ipmi-agent-spaces',
					'ipmi_sensor' => '  ipmi_sensor   ',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'SSH agent',
					'name' => 'SSH agent error',
					'key' => 'item-ssh-agent-error',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/username": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'TELNET agent',
					'name' => 'TELNET agent error',
					'key' => 'item-telnet-agent-error',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/username": cannot be empty.'
					]
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'JMX agent',
					'name' => 'JMX agent',
					'key' => 'item-jmx-agent',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Calculated',
					'name' => 'Calculated',
					'key' => 'item-calculated',
					'params_f' => '"formula"',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_GOOD,
					'type' => 'Dependent item',
					'name' => 'Dependent item',
					'key' => 'item-dependent',
					'master_item' => 'testFormItem',
					'dbCheck' => true,
					'formCheck' => true
				]
			],
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Calculated',
					'name' => 'Calculated',
					'key' => 'item-calculated',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Invalid parameter "/1/params": cannot be empty.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'Database monitor',
					'name' => 'Database monitor',
					'params_ap' => 'query',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Check the key, please. Default example was passed.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'SSH agent',
					'name' => 'SSH agent',
					'username' => 'zabbix',
					'params_es' => 'script to be executed',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Check the key, please. Default example was passed.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'TELNET agent',
					'name' => 'TELNET agent',
					'username' => 'zabbix',
					'params_es' => 'script to be executed',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Check the key, please. Default example was passed.'
					]
				]
			],
			// Default
			[
				[
					'expected' => TEST_BAD,
					'type' => 'JMX agent',
					'name' => 'JMX agent',
					'username' => 'zabbix',
					'error_msg' => 'Cannot add item',
					'errors' => [
						'Incorrect value for field "key": cannot be empty.'
					]
				]
			]
		];
	}

	/**
	 * @dataProvider create
	 */
	public function testFormItem_SimpleCreate($data) {
		$this->zbxTestLogin(self::HOST_LIST_PAGE);
		$this->filterEntriesAndOpenItems();
		$this->zbxTestCheckTitle('Configuration of items');
		$this->zbxTestCheckHeader('Items');

		$this->zbxTestContentControlButtonClickTextWait('Create item');
		$this->zbxTestCheckTitle('Configuration of items');
		$dialog = COverlayDialogElement::find()->one()->waitUntilReady();
		$form = $dialog->asForm();

		if (isset($data['type'])) {
			$this->zbxTestDropdownSelect('type', $data['type']);
			$type = $data['type'];
		}
		else {
			$type = $this->zbxTestGetSelectedLabel('type');
		}

		if (isset($data['name'])) {
			$this->zbxTestInputType('name', $data['name']);
		}
		$name = $this->zbxTestGetValue("//input[@id='name']");

		if (isset($data['key'])) {
			$this->zbxTestInputType('key', $data['key']);
		}
		$key = $this->zbxTestGetValue("//input[@id='key']");

		if (isset($data['username'])) {
			$this->zbxTestInputType('username', $data['username']);
		}

		if (isset($data['ipmi_sensor'])) {
			$this->zbxTestInputType('ipmi_sensor', $data['ipmi_sensor']);
			$ipmi_sensor = $this->zbxTestGetValue("//input[@id='ipmi_sensor']");
		}

		if (isset($data['script'])) {
			$form->getField('Script')->fill($data['script']);
		}

		if (isset($data['params_value'])) {
			$form->getField('name:parameters[0][value]')->fill($data['params_value']);
		}

		if (isset($data['allowed_hosts'])) {
			$this->zbxTestInputType('trapper_hosts', $data['allowed_hosts']);
		}

		if (isset($data['params_f'])) {
			$this->zbxTestInputType('params_f', $data['params_f']);
		}

		if (isset($data['params_es'])) {
			$this->zbxTestInputTypeWait('params_es', $data['params_es']);
		}

		if (isset($data['params_ap'])) {
			$this->zbxTestInputTypeWait('params_ap', $data['params_ap']);
		}

		if (isset($data['delay']))	{
			$this->zbxTestInputTypeOverwrite('delay', $data['delay']);
		}

		if (array_key_exists('master_item',$data))	{
			$this->zbxTestClickButtonMultiselect('master_itemid');
			$master_overlay = COverlayDialogElement::find()->all()->last()->waitUntilReady();
			$this->assertEquals('Items', $master_overlay->getTitle());
			$master_overlay->query('link:'.$data['master_item'])->one()->click();
		}

		if (array_key_exists('snmp_oid', $data))	{
			$this->zbxTestInputTypeOverwrite('snmp_oid', $data['snmp_oid']);
		}

		// Check hidden update and custom interval for mqtt.get key.
		if (CTestArrayHelper::get($data, 'type') === 'Zabbix agent (active)'
				&& substr(CTestArrayHelper::get($data, 'key'), 0, 8) === 'mqtt.get') {
			$this->assertFalse($form->getField('Update interval')->isDisplayed());
			$this->assertFalse($form->getField('Custom intervals')->isDisplayed());
		}

		$itemFlexFlag = true;
		if (isset($data['flexPeriod'])) {

			$itemCount = 0;
			foreach ($data['flexPeriod'] as $period) {
				$this->zbxTestInputType('delay_flex_'.$itemCount.'_period', $period['flexTime']);

				if (isset($period['flexDelay'])) {
					$this->zbxTestInputType('delay_flex_'.$itemCount.'_delay', $period['flexDelay']);
				}
				$itemCount ++;
				$form->query("xpath://div[@id='js-item-flex-intervals-field']//button[@class='btn-link element-table-add']")
						->one()->click();

				$this->zbxTestAssertVisibleId('delay_flex_'.$itemCount.'_delay');
				$this->zbxTestAssertVisibleId('delay_flex_'.$itemCount.'_period');

				if (isset($period['remove'])) {
					$form->query("xpath://table[@id='delay-flex-table']/tbody/tr[1]/td[4]/button")
							->one()->click();
				}
			}
		}

		if (isset($data['history'])) {
			$this->zbxTestInputTypeOverwrite('history', $data['history']);
		}

		if (isset($data['trends'])) {
			$this->zbxTestInputTypeOverwrite('trends', $data['trends']);
		}

		switch ($type) {
			case 'Zabbix agent':
			case 'Simple check':
			case 'SNMP agent':
			case 'SNMP trap':
			case 'External check':
			case 'IPMI agent':
			case 'SSH agent':
			case 'TELNET agent':
			case 'JMX agent':
				$interfaceid = $this->zbxTestGetText('//z-select[@id="interface-select"]//li[not(@disabled)]');
				break;
			default:
				$this->zbxTestAssertNotVisibleId('interface-select');
		}

		$value_type = $this->zbxTestGetSelectedLabel('value_type');
		if ($itemFlexFlag == true) {
			$dialog->getFooter()->query('button:Add')->one()->click();
			$expected = $data['expected'];
			switch ($expected) {
				case TEST_GOOD:
					COverlayDialogElement::ensureNotPresent();
					$this->zbxTestCheckTitle('Configuration of items');
					$this->zbxTestWaitUntilMessageTextPresent('msg-good', 'Item added');
					break;

				case TEST_BAD:
					$this->zbxTestCheckTitle('Configuration of items');
					$this->assertMessage(TEST_BAD, $data['error_msg'], $data['errors']);
					$this->zbxTestTextPresent(['Host', 'Name', 'Key']);

					if (isset($data['formula'])) {
						$this->zbxTestAssertElementValue('formula', $data['formulaValue']);
					}

					$dialog->close();
					break;
				}
			}

		if (isset($data['dbCheck'])) {
			$result = DBselect("SELECT name,key_,value_type FROM items where hostid=40001 and key_ = '".$key."'");
			while ($row = DBfetch($result)) {
				$this->assertEquals($row['name'], $name);
				$this->assertEquals($row['key_'], $key);

				switch($row['value_type'])	{
					case ITEM_VALUE_TYPE_FLOAT:
						$value_typeDB = 'Numeric (float)';
						break;
					case ITEM_VALUE_TYPE_STR:
						$value_typeDB = 'Character';
						break;
					case ITEM_VALUE_TYPE_LOG:
						$value_typeDB = 'Log';
						break;
					case ITEM_VALUE_TYPE_UINT64:
						$value_typeDB = 'Numeric (unsigned)';
						break;
					case ITEM_VALUE_TYPE_TEXT:
						$value_typeDB = 'Text';
						break;
				}
				$this->assertEquals($value_typeDB, $value_type);
			}
		}
		if (isset($data['formCheck'])) {
			$this->query('class:btn-overlay-close')->one()->click();
			$this->page->waitUntilReady();
			$this->query('xpath://form[@name="item_list"]/table[@class="list-table"]')->asTable()->one()
					->query('link', $name)->one()->click();
			$dialog_check = COverlayDialogElement::find()->one()->waitUntilReady();
			$check_form = $dialog_check->asForm();
			$this->assertEquals($name, $check_form->getField('Name')->getValue());
			$this->assertEquals($key, $check_form->getField('Key')->getValue());
			$this->zbxTestAssertElementPresentXpath("//z-select[@id='type']//li[text()='$type']");
			switch ($type) {
				case 'Zabbix agent':
				case 'Simple check':
				case 'SNMP agent':
				case 'SNMP trap':
				case 'External check':
				case 'IPMI agent':
				case 'SSH agent':
				case 'TELNET agent':
				case 'JMX agent':
					$this->zbxTestAssertElementPresentXpath('//z-select[@id="interface-select"]//li[text()="'.$interfaceid.'"]');
					break;
				case 'Zabbix agent (active)':
					$this->zbxTestAssertNotVisibleId('interfaceid');
					// Check hidden update and custom interval for mqtt.get key.
					if (substr(CTestArrayHelper::get($data, 'key'), 0, 8) === 'mqtt.get') {
						$this->assertFalse($form->getField('Update interval')->isDisplayed());
						$this->assertFalse($form->getField('Custom intervals')->isDisplayed());
					}
					else {
						$this->assertTrue($form->getField('Update interval')->isDisplayed());
						$this->assertTrue($form->getField('Custom intervals')->isDisplayed());
					}
					break;
				default:
					$this->zbxTestAssertNotVisibleId('interface-select');
			}
			$this->zbxTestAssertElementPresentXpath("//z-select[@id='value_type']//li[text()='$value_type']");

			// "Execute now" button availability
			if (in_array($type, ['Zabbix agent (active)', 'SNMP trap', 'Zabbix trapper'])) {
				$this->assertFalse($dialog_check->getFooter()->query('button:Execute now')->one()->isClickable());
			}
			else {
				$dialog_check->getFooter()->query('button:Execute now')->one()->click();
				$this->assertMessage(TEST_GOOD, 'Request sent successfully');
			}

			if (isset($data['ipmi_sensor'])) {
				$ipmiValue = $this->zbxTestGetValue("//input[@id='ipmi_sensor']");
				$this->assertEquals($ipmi_sensor, $ipmiValue);
			}

			$dialog_check->close();
		}
	}

	public function testFormItem_HousekeeperUpdate() {
		$this->zbxTestLogin('zabbix.php?action=housekeeping.edit');

		$this->zbxTestCheckboxSelect('hk_history_global', false);
		$this->zbxTestCheckboxSelect('hk_trends_global', false);

		$this->zbxTestClickWait('update');

		$this->zbxTestOpen(self::HOST_LIST_PAGE);
		$this->filterEntriesAndOpenItems();

		$this->zbxTestAssertElementNotPresentId('history_mode_hint');
		$this->zbxTestAssertElementNotPresentId('trends_mode_hint');

		$this->zbxTestOpen('zabbix.php?action=housekeeping.edit');

		$this->zbxTestCheckboxSelect('hk_history_global');
		$this->zbxTestInputType('hk_history', '99d');

		$this->zbxTestCheckboxSelect('hk_trends_global');
		$this->zbxTestInputType('hk_trends', '455d');

		$this->zbxTestClickWait('update');

		$this->zbxTestOpen(self::HOST_LIST_PAGE);
		$this->filterEntriesAndOpenItems();
		$this->zbxTestClickLinkTextWait($this->item);
		$dialog = COverlayDialogElement::find()->waitUntilReady()->one();
		$form = $dialog->asForm();
		$form->getLabel('History')->query("xpath:span[@class='js-hint']/button")->one()->click();
		$this->zbxTestAssertElementText("//div[@class='overlay-dialogue wordbreak']", 'Overridden by global housekeeping settings (99d)');
		$form->getLabel('Trends')->query("xpath:span[@class='js-hint']/button")->one()->click();
		$this->zbxTestAssertElementText("//div[@class='overlay-dialogue wordbreak'][2]", 'Overridden by global housekeeping settings (455d)');
		$dialog->close();

		$this->zbxTestOpen('zabbix.php?action=housekeeping.edit');

		$this->zbxTestInputType('hk_history', 90);
		$this->zbxTestCheckboxSelect('hk_history_global', false);

		$this->zbxTestInputType('hk_trends', 365);
		$this->zbxTestCheckboxSelect('hk_trends_global', false);

		$this->zbxTestClickWait('update');

		$this->zbxTestOpen(self::HOST_LIST_PAGE);
		$this->filterEntriesAndOpenItems();
		$this->zbxTestAssertElementNotPresentId('history_mode_hint');
		$this->zbxTestAssertElementNotPresentId('trends_mode_hint');
	}

	/**
	 * Function for filtering necessary hosts or templates and opening their Items.
	 */
	private function filterEntriesAndOpenItems() {
		$form = $this->query('name:zbx_filter')->asForm()->waitUntilReady()->one();
		$form->fill(['Name' => $this->host]);
		$this->query('button:Apply')->one()->waitUntilClickable()->click();
		$this->query('xpath://table[@class="list-table"]')->asTable()->one()->findRow('Name', $this->host)
				->getColumn('Items')->query('link:Items')->one()->click();
	}
}
