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.
		
		
		
		
		
			
		
			
				
					
					
						
							2114 lines
						
					
					
						
							54 KiB
						
					
					
				
			
		
		
	
	
							2114 lines
						
					
					
						
							54 KiB
						
					
					
				| <?php
 | |
| /*
 | |
| ** Zabbix
 | |
| ** Copyright (C) 2001-2023 Zabbix SIA
 | |
| **
 | |
| ** This program is free software; you can redistribute it and/or modify
 | |
| ** it under the terms of the GNU General Public License as published by
 | |
| ** the Free Software Foundation; either version 2 of the License, or
 | |
| ** (at your option) any later version.
 | |
| **
 | |
| ** This program is distributed in the hope that it will be useful,
 | |
| ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | |
| ** GNU General Public License for more details.
 | |
| **
 | |
| ** You should have received a copy of the GNU General Public License
 | |
| ** along with this program; if not, write to the Free Software
 | |
| ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | |
| **/
 | |
| 
 | |
| require_once dirname(__FILE__).'/../../include/CWebTest.php';
 | |
| require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
 | |
| 
 | |
| /**
 | |
|  * @backup items, ids
 | |
|  */
 | |
| class testFormLowLevelDiscoveryOverrides extends CWebTest {
 | |
| 
 | |
| 	const HOST_ID = 40001;
 | |
| 	const UPDATED_ID = 133800;
 | |
| 
 | |
| 	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]'
 | |
| 		]
 | |
| 	];
 | |
| 
 | |
| 
 | |
| 	public static $created_id;
 | |
| 	public static $old_hash;
 | |
| 
 | |
| 	/**
 | |
| 	 * Attach Behaviors to the test.
 | |
| 	 *
 | |
| 	 * @return array
 | |
| 	 */
 | |
| 	public function getBehaviors() {
 | |
| 		return ['class' => CMessageBehavior::class];
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Overrides data for LLD creation.
 | |
| 	 */
 | |
| 	public static function getCreateData() {
 | |
| 		return [
 | |
| 			// #0.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => ''
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Name": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #1.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override without actions'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #2.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override without actions'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #3.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override without actions'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Graph prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #4.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override without actions'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #5.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty tags in trigger prototype'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype',
 | |
| 										'Tags' => []
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tags": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #6.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty tag name in trigger prototype'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype',
 | |
| 										'Tags' => [
 | |
| 											['tag' => '', 'value' => 'value1']
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tag": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #7.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty template'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Link templates' => []
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Link templates": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #8.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty tag name in host prototype'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Tags' => [
 | |
| 											['tag' => '', 'value' => 'value1']
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tag": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #9.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty tags in host prototype'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Tags' => []
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tags": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #10.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty delay'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => ''
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Update interval": invalid delay.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #11.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with zero delay'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '0'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Item will not be refreshed. Specified update interval requires '.
 | |
| 									'having at least one either flexible or scheduling interval.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #12.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with 2 days delay'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '2d'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Item will not be refreshed. Update interval should be between 1s and 1d. '.
 | |
| 									'Also Scheduled/Flexible intervals can be used.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #13.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty interval'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '50m',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_ADD,
 | |
| 												'type' => 'Flexible',
 | |
| 												'delay' => '',
 | |
| 												'period' => '1-5,01:01-13:05'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #14.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty period'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '50m',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_ADD,
 | |
| 												'type' => 'Flexible',
 | |
| 												'delay' => '20s',
 | |
| 												'period' => ''
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #15.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with wrong period'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '50m',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_ADD,
 | |
| 												'type' => 'Flexible',
 | |
| 												'delay' => '20s',
 | |
| 												'period' => '1-2'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "1-2".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #16.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with wrong scheduling interval'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '50m',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_ADD,
 | |
| 												'type' => 'Scheduling',
 | |
| 												'delay' => 'wd1-9'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "wd1-9".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #17.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty history'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype',
 | |
| 										'History storage period' => [
 | |
| 											'ophistory_history_mode' => 'Storage period',
 | |
| 											'ophistory_history' => ''
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "History storage period": a time unit is expected.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #18.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override with empty history'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype',
 | |
| 										'Trend storage period' => [
 | |
| 											'optrends_trends_mode' => 'Storage period',
 | |
| 											'optrends_trends' => ''
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Trend storage period": a time unit is expected.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #19.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_GOOD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Minimal override'
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// #20.
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_GOOD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override_1',
 | |
| 								'If filter matches' => 'Stop processing'
 | |
| 							],
 | |
| 							'Filters' => [
 | |
| 								'Type of calculation' => 'Custom expression',
 | |
| 								'formula' => '(A and B) or (C and D)',
 | |
| 								'filter_conditions' => [
 | |
| 									[
 | |
| 										'action' => USER_ACTION_UPDATE,
 | |
| 										'index' => 0,
 | |
| 										'macro' => '{#MACRO1}',
 | |
| 										'operator' => 'does not match',
 | |
| 										'value' => 'expression_1'
 | |
| 									],
 | |
| 									[
 | |
| 										'macro' => '{#MACRO2}',
 | |
| 										'operator' => 'matches',
 | |
| 										'value' => 'expression_2'
 | |
| 									],
 | |
| 									[
 | |
| 										'macro' => '{#MACRO3}',
 | |
| 										'operator' => 'exists'
 | |
| 									],
 | |
| 									[
 | |
| 										'macro' => '{#MACRO4}',
 | |
| 										'operator' => 'does not exist'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype',
 | |
| 										'Condition' => ['operator' => 'does not match', 'value' => 'item_pattern'],
 | |
| 										'Create enabled' => 'No',
 | |
| 										'Discover' => 'No',
 | |
| 										'History storage period' => [
 | |
| 											'ophistory_history_mode' => 'Storage period',
 | |
| 											'ophistory_history' => '500d'
 | |
| 										],
 | |
| 										'Trend storage period' => [
 | |
| 											'optrends_trends_mode' => 'Storage period',
 | |
| 											'optrends_trends' => '200d'
 | |
| 										]
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '50m',
 | |
| 										'Custom intervals' => [
 | |
| 											['type' => 'Flexible', 'delay' => '60s', 'period' => '1-5,01:01-13:05'],
 | |
| 											['type' => 'Scheduling', 'delay' => 'wd1-3h10-17']
 | |
| 										]
 | |
| 									]
 | |
| 								],
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype',
 | |
| 										'Condition' => ['operator' => 'contains', 'value' => 'trigger_Pattern'],
 | |
| 										'Create enabled' => 'No',
 | |
| 										'Discover' => 'No',
 | |
| 										'Severity' => 'Warning',
 | |
| 										'Tags' => [
 | |
| 											['tag' => 'tag1', 'value' => 'value1'],
 | |
| 											['tag' => 'tag2', 'value' => 'value2']
 | |
| 										]
 | |
| 									]
 | |
| 								],
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Graph prototype',
 | |
| 										'Condition' => ['operator' => 'matches', 'value' => 'Graph_Pattern'],
 | |
| 										'Discover' => 'Yes'
 | |
| 									]
 | |
| 								],
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Condition' => ['operator' => 'does not match', 'value' => 'Host_Pattern'],
 | |
| 										'Create enabled' => 'Yes',
 | |
| 										'Discover' => 'Yes',
 | |
| 										'Link templates' => 'Test Item Template',
 | |
| 										'Host inventory' => 'Disabled'
 | |
| 									]
 | |
| 								]
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override_2',
 | |
| 								'If filter matches' => 'Continue overrides'
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Graph prototype',
 | |
| 										'Condition' => ['operator' => 'matches', 'value' => '2Graph_Pattern'],
 | |
| 										'Discover' => 'No'
 | |
| 									]
 | |
| 								],
 | |
| 								[
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Condition' => ['operator' => 'does not match', 'value' => '2Host_Pattern'],
 | |
| 										'Create enabled' => 'Yes',
 | |
| 										'Discover' => 'No',
 | |
| 										'Link templates' => 'Test Item Template',
 | |
| 										'Host inventory' => 'Automatic'
 | |
| 									]
 | |
| 								]
 | |
| 							]
 | |
| 						]
 | |
| 					],
 | |
| 					'screenshot' => true
 | |
| 				]
 | |
| 			]
 | |
| 		];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @dataProvider getCreateData
 | |
| 	 */
 | |
| 	public function testFormLowLevelDiscoveryOverrides_Create($data) {
 | |
| 		$this->overridesCreate($data);
 | |
| 	}
 | |
| 
 | |
| 	private function overridesCreate($data) {
 | |
| 		$this->page->login()->open('host_discovery.php?form=create&context=host&hostid='.self::HOST_ID);
 | |
| 		$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
 | |
| 		$key = 'lld_override'.time();
 | |
| 		$form->fill([
 | |
| 			'Name' => 'LLD with overrides',
 | |
| 			'Key' => $key
 | |
| 		]);
 | |
| 		$form->selectTab('Overrides');
 | |
| 		$form->invalidate();
 | |
| 		$override_container = $form->getField('Overrides')->asTable();
 | |
| 
 | |
| 		// Add overrides from data to lld rule.
 | |
| 		foreach($data['overrides'] as $i => $override){
 | |
| 			$override_container->query('button:Add')->one()->click();
 | |
| 			$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 
 | |
| 			// Fill Override name and what to do if Filter matches.
 | |
| 			if (array_key_exists('fields', $override)) {
 | |
| 				$override_overlay->fill($override['fields']);
 | |
| 			}
 | |
| 			$this->fillOverrideFilter($override);
 | |
| 			$this->fillOverrideOperations($data, $override);
 | |
| 
 | |
| 			$this->checkSubmittedOverlay($data['expected'], $override_overlay, CTestArrayHelper::get($override, 'error'));
 | |
| 
 | |
| 			if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
 | |
| 				// Check that Override with correct name was added to Overrides table.
 | |
| 				$this->assertEquals(CTestArrayHelper::get($override, 'fields.Name'),
 | |
| 						$override_container->getRow($i)->getColumn('Name')->getText()
 | |
| 				);
 | |
| 				// Check that Override in table has correct processing status.
 | |
| 				$stop_processing = (CTestArrayHelper::get($override,
 | |
| 						'fields.If filter matches') === 'Stop processing') ? 'Yes' : 'No';
 | |
| 				$this->assertEquals($stop_processing,
 | |
| 						$override_container->getRow($i)->getColumn('Stop processing')->getText()
 | |
| 				);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Take a screenshot to test draggable object position for overrides.
 | |
| 		if (array_key_exists('screenshot', $data)) {
 | |
| 			$this->page->removeFocus();
 | |
| 			$this->assertScreenshot($this->query('class:lld-overrides-table')->one(), 'LLD override');
 | |
| 		}
 | |
| 
 | |
| 		if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
 | |
| 			// Submit LLD create.
 | |
| 			$form->submit();
 | |
| 			$this->assertMessage(TEST_GOOD, 'Discovery rule created');
 | |
| 			self::$created_id = CDBHelper::getValue('SELECT itemid FROM items WHERE key_='.zbx_dbstr($key));
 | |
| 		}
 | |
| 
 | |
| 		$this->checkSavedState($data);
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * Overrides data for LLD update.
 | |
| 	 */
 | |
| 	public static function getUpdateData() {
 | |
| 		return [
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'fields' => [
 | |
| 								'Name' => ''
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Name": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_ADD,
 | |
| 							'fields' => [
 | |
| 								'Name' => ''
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Name": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_ADD,
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Override for update 1'
 | |
| 							],
 | |
| 							'error' => 'Override with name "Override for update 1" already exists.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_ADD,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_ADD,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_ADD,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Graph prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_ADD,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Item prototype',
 | |
| 										'Create enabled' => null,
 | |
| 										'Discover' => null,
 | |
| 										'History storage period' => null,
 | |
| 										'Trend storage period' => null
 | |
| 									],
 | |
| 									'Update interval' => null
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype',
 | |
| 										'Create enabled' => null,
 | |
| 										'Discover' => null,
 | |
| 										'Severity' => null,
 | |
| 										'Tags' => null
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Graph prototype',
 | |
| 										'Discover' => null
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Create enabled' => null,
 | |
| 										'Discover' => null,
 | |
| 										'Link templates' => null,
 | |
| 										'Tags' => null,
 | |
| 										'Host inventory' => null
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'At least one action is mandatory.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype',
 | |
| 										'Tags' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'tag' => '',
 | |
| 												'value' => ''
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tags": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Trigger prototype',
 | |
| 										'Tags' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'tag' => '',
 | |
| 												'value' => 'value1'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tag": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Link templates' => []
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Link templates": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Tags' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'tag' => '',
 | |
| 												'value' => ''
 | |
| 											],
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 1
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tags": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Tags' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'tag' => '',
 | |
| 												'value' => 'new_value'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tag": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Tags' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 1
 | |
| 											],
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 0
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Tags": cannot be empty.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => ''
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Update interval": invalid delay.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '0',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 1
 | |
| 											],
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 0
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Item will not be refreshed. Specified update interval requires '.
 | |
| 									'having at least one either flexible or scheduling interval.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '2d',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 1
 | |
| 											],
 | |
| 											[
 | |
| 												'action' => USER_ACTION_REMOVE,
 | |
| 												'index' => 0
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Item will not be refreshed. Update interval should be between 1s and 1d. '.
 | |
| 									'Also Scheduled/Flexible intervals can be used.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'delay' => ''
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'period' => ''
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'period' => '1-2'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "1-2".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'Update interval' => [
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 1,
 | |
| 												'delay' => 'wd1-9'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Invalid interval "wd1-9".'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'fields' => [
 | |
| 										'History storage period' => [
 | |
| 											'ophistory_history_mode' => 'Storage period',
 | |
| 											'ophistory_history' => ''
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "History storage period": a time unit is expected.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'fields' => [
 | |
| 										'Trend storage period' => [
 | |
| 											'optrends_trends_mode' => 'Storage period',
 | |
| 											'optrends_trends' => ''
 | |
| 										]
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'error' => 'Incorrect value for field "Trend storage period": a time unit is expected.'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_GOOD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_REMOVE,
 | |
| 							'name' => 'Override for update 1'
 | |
| 						],
 | |
| 						[
 | |
| 							'action' => USER_ACTION_REMOVE,
 | |
| 							'name' => 'Override for update 2'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_GOOD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Filters' => [
 | |
| 								'formula' => 'A and B and C and D and E',
 | |
| 								'filter_conditions' => [
 | |
| 									[
 | |
| 										'action' => USER_ACTION_ADD,
 | |
| 										'macro' => '{#UPDATED_MACRO3}',
 | |
| 										'operator' => 'does not match',
 | |
| 										'value' => 'ADDED expression_3'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_ADD,
 | |
| 									'fields' => [
 | |
| 										'Object' => 'Host prototype',
 | |
| 										'Condition' => ['operator' => 'contains', 'value' => 'new host pattern'],
 | |
| 										'Create enabled' => 'No',
 | |
| 										'Discover' => 'Yes',
 | |
| 										'Link templates' => 'Test Item Template',
 | |
| 										'Tags' => [
 | |
| 											['tag' => 'added_name1', 'value' => 'added_value1']
 | |
| 										],
 | |
| 										'Host inventory' => 'Disabled'
 | |
| 									]
 | |
| 								]
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_GOOD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'fields' => [
 | |
| 								'Name' => 'Updated Override for update 1',
 | |
| 								'If filter matches' => 'Stop processing'
 | |
| 							],
 | |
| 							'Filters' => [
 | |
| 								'Type of calculation' => 'Custom expression',
 | |
| 								'formula' => 'A and B and C and D',
 | |
| 								'filter_conditions' => [
 | |
| 									[
 | |
| 										'action' => USER_ACTION_UPDATE,
 | |
| 										'index' => 0,
 | |
| 										'macro' => '{#UPDATED_MACRO1}',
 | |
| 										'operator' => 'does not match',
 | |
| 										'value' => 'UPDATED expression_1'
 | |
| 									],
 | |
| 									[
 | |
| 										'action' => USER_ACTION_UPDATE,
 | |
| 										'index' => 1,
 | |
| 										'macro' => '{#UPDATED_MACRO2}',
 | |
| 										'operator' => 'matches',
 | |
| 										'value' => 'UPDATED expression_2'
 | |
| 									],
 | |
| 									[
 | |
| 										'action' => USER_ACTION_UPDATE,
 | |
| 										'index' => 2,
 | |
| 										'macro' => '{#UPDATED_MACRO3}',
 | |
| 										'operator' => 'does not exist'
 | |
| 									],
 | |
| 									[
 | |
| 										'action' => USER_ACTION_UPDATE,
 | |
| 										'index' => 3,
 | |
| 										'macro' => '{#UPDATED_MACRO4}',
 | |
| 										'operator' => 'exists'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'fields' => [
 | |
| 										'Create enabled' => 'No',
 | |
| 										'Discover' => 'No',
 | |
| 										'History storage period' => [
 | |
| 											'ophistory_history_mode' => 'Storage period',
 | |
| 											'ophistory_history' => '500d'
 | |
| 										],
 | |
| 										'Trend storage period' => [
 | |
| 											'optrends_trends_mode' => 'Storage period',
 | |
| 											'optrends_trends' => '200d'
 | |
| 										]
 | |
| 									],
 | |
| 									'Update interval' => [
 | |
| 										'Delay' => '50m',
 | |
| 										'Custom intervals' => [
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 0,
 | |
| 												'type' => 'Scheduling',
 | |
| 												'delay' => 'wd1-3h10-17'
 | |
| 											],
 | |
| 											[
 | |
| 												'action' => USER_ACTION_UPDATE,
 | |
| 												'index' => 1,
 | |
| 												'type' => 'Flexible',
 | |
| 												'delay' => '60s',
 | |
| 												'period' => '1-5,01:01-13:05'
 | |
| 											]
 | |
| 										]
 | |
| 									]
 | |
| 								],
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Create enabled' => 'No',
 | |
| 										'Discover' => 'Yes',
 | |
| 										'Severity' => null,
 | |
| 										'Tags' => null
 | |
| 									]
 | |
| 								]
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 0,
 | |
| 									'fields' => [
 | |
| 										'Discover' => 'No'
 | |
| 									]
 | |
| 								],
 | |
| 								[
 | |
| 									'action' => USER_ACTION_UPDATE,
 | |
| 									'index' => 1,
 | |
| 									'fields' => [
 | |
| 										'Create enabled' => 'No',
 | |
| 										'Discover' =>'Yes',
 | |
| 										'Link templates' => null,
 | |
| 										'Tags' => null,
 | |
| 										'Host inventory' => null
 | |
| 									]
 | |
| 								]
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_GOOD,
 | |
| 					'overrides' => [
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 1',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_REMOVE,
 | |
| 									'index' => 1,
 | |
| 									'fields' =>
 | |
| 										[
 | |
| 											'Object' => 'Trigger prototype',
 | |
| 											'Condition' => ['operator' => 'does not equal', 'value' => 'test trigger pattern']
 | |
| 										]
 | |
| 								]
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'action' => USER_ACTION_UPDATE,
 | |
| 							'name' => 'Override for update 2',
 | |
| 							'Operations' => [
 | |
| 								[
 | |
| 									'action' => USER_ACTION_REMOVE,
 | |
| 									'index' => 1,
 | |
| 									'fields' =>
 | |
| 										[
 | |
| 											'Object' => 'Host prototype',
 | |
| 											'Condition' => ['operator' => 'does not match', 'value' => 'test host pattern']
 | |
| 										]
 | |
| 								]
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			]
 | |
| 		];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @dataProvider getUpdateData
 | |
| 	 *
 | |
| 	 * @backup items
 | |
| 	 */
 | |
| 	public function testFormLowLevelDiscoveryOverrides_Update($data) {
 | |
| 		$this->overridesUpdate($data);
 | |
| 	}
 | |
| 
 | |
| 	private function overridesUpdate($data) {
 | |
| 		self::$old_hash = CDBHelper::getHash('SELECT * FROM items WHERE flags=1 ORDER BY itemid');
 | |
| 		$this->page->login()->open('host_discovery.php?form=update&context=host&itemid='.self::UPDATED_ID);
 | |
| 		$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
 | |
| 		$form->selectTab('Overrides');
 | |
| 		$form->invalidate();
 | |
| 		$override_container = $form->getField('Overrides')->asTable();
 | |
| 
 | |
| 		$sources = [
 | |
| 			[
 | |
| 				'fields' => [
 | |
| 					'Name' => 'Override for update 1',
 | |
| 					'If filter matches' => 'Continue overrides'
 | |
| 				],
 | |
| 				'Filters' => [
 | |
| 					'Type of calculation' => 'And',
 | |
| 					'formula' => 'A and B and C and D',
 | |
| 					'filter_conditions' => [
 | |
| 						[
 | |
| 							'macro' => '{#MACRO1}',
 | |
| 							'operator' => 'matches',
 | |
| 							'value' => 'test expression_1'
 | |
| 						],
 | |
| 						[
 | |
| 							'macro' => '{#MACRO2}',
 | |
| 							'operator' => 'does not match',
 | |
| 							'value' => 'test expression_2'
 | |
| 						],
 | |
| 						[
 | |
| 							'macro' => '{#MACRO3}',
 | |
| 							'operator' => 'exists'
 | |
| 						],
 | |
| 						[
 | |
| 							'macro' => '{#MACRO4}',
 | |
| 							'operator' => 'does not exist'
 | |
| 						]
 | |
| 					]
 | |
| 				],
 | |
| 				'Operations' => [
 | |
| 					[
 | |
| 						'Object' => 'Item prototype',
 | |
| 						'Condition' => ['operator' => 'equals', 'value' => 'test item pattern'],
 | |
| 						'Create enabled' => 'Yes',
 | |
| 						'Discover' => 'Yes',
 | |
| 						// TODO: uncomment after fix DEV-1071 and it is possible to check this field.
 | |
| //						'Update interval' => [
 | |
| //							'Delay' => '1m',
 | |
| //							'Custom intervals' => [
 | |
| //								['type' => 'Flexible', 'delay' => '50s', 'period' => '1-7,00:00-24:00'],
 | |
| //								['type' => 'Scheduling', 'delay' => 'wd1-5h9-18']
 | |
| //							]
 | |
| //						],
 | |
| 						'History storage period' => ['ophistory_history_mode' => 'Do not keep history'],
 | |
| 						'Trend storage period' => ['optrends_trends_mode' => 'Do not keep trends']
 | |
| 					],
 | |
| 					[
 | |
| 						'Object' => 'Trigger prototype',
 | |
| 						'Condition' => ['operator' => 'does not equal', 'value' => 'test trigger pattern'],
 | |
| 						'Create enabled' => null,
 | |
| 						'Discover' => null,
 | |
| 						'Severity' => 'Warning',
 | |
| 						'Tags' => [
 | |
| 							['tag' => 'tag1', 'value' => 'value1']
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				'fields' => [
 | |
| 					'Name' => 'Override for update 2',
 | |
| 					'If filter matches' => 'Continue overrides'
 | |
| 				],
 | |
| 				'Operations' => [
 | |
| 					[
 | |
| 						'Object' => 'Graph prototype',
 | |
| 						'Condition' => ['operator' => 'matches', 'value' => 'test graph pattern'],
 | |
| 						'Discover' => 'Yes'
 | |
| 					],
 | |
| 					[
 | |
| 						'Object' => 'Host prototype',
 | |
| 						'Condition' => ['operator' => 'does not match', 'value' => 'test host pattern'],
 | |
| 						'Create enabled' => null,
 | |
| 						'Discover' => null,
 | |
| 						'Link templates' => 'Test Item Template',
 | |
| 						'Tags' => [
 | |
| 							['tag' => 'name1', 'value' => 'value1'],
 | |
| 							['tag' => 'name2', 'value' => 'value2']
 | |
| 						],
 | |
| 						'Host inventory' => 'Automatic'
 | |
| 					]
 | |
| 				]
 | |
| 			]
 | |
| 		];
 | |
| 
 | |
| 		foreach ($data['overrides'] as $i => $override) {
 | |
| 			$override_action = CTestArrayHelper::get($override, 'action', USER_ACTION_ADD);
 | |
| 
 | |
| 			// Preparing reference data for overrides.
 | |
| 			switch ($override_action) {
 | |
| 				case USER_ACTION_ADD:
 | |
| 					$sources[] = $override;
 | |
| 					break;
 | |
| 
 | |
| 				case USER_ACTION_REMOVE:
 | |
| 					foreach ($sources as $id => $source) {
 | |
| 						if ($source['fields']['Name'] === $override['name']) {
 | |
| 							unset($sources[$id]);
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case USER_ACTION_UPDATE:
 | |
| 					// Find overrides by name.
 | |
| 					foreach ($sources as $id => $source) {
 | |
| 						if ($source['fields']['Name'] === $override['name']) {
 | |
| 							break;
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					$this->assertNotNull($id, 'Cannot find reference data by override name '.$override['name']);
 | |
| 
 | |
| 					// Check if source has fields from data to update them.
 | |
| 					foreach (CTestArrayHelper::get($override, 'fields', []) as $key => $value) {
 | |
| 						$this->assertArrayHasKey($key, $sources[$id]['fields'], 'Cannot find field '.$key.' in source');
 | |
| 						$sources[$id]['fields'][$key] = $value;
 | |
| 					}
 | |
| 
 | |
| 					// Preparing reference data for Filter conditions.
 | |
| 					$conditions = [];
 | |
| 					foreach (CTestArrayHelper::get($override, 'Filters', []) as $key => $value) {
 | |
| 						if ($key === 'filter_conditions') {
 | |
| 							$conditions = $value;
 | |
| 							continue;
 | |
| 						}
 | |
| 
 | |
| 						$sources[$id]['Filters'][$key] = $value;
 | |
| 					}
 | |
| 
 | |
| 					foreach ($conditions as $condition) {
 | |
| 						switch($condition['action']) {
 | |
| 							case USER_ACTION_ADD:
 | |
| 								$sources[$id]['Filters']['filter_conditions'][] = $condition;
 | |
| 								break;
 | |
| 
 | |
| 							case USER_ACTION_UPDATE:
 | |
| 								foreach ($condition as $key => $value) {
 | |
| 									// Skipping 'action' and 'index' fields from reference data.
 | |
| 									if (in_array($key, ['action', 'index'])) {
 | |
| 										continue;
 | |
| 									}
 | |
| 
 | |
| 									$sources[$id]['Filters']['filter_conditions'][$condition['index']][$key] = $value;
 | |
| 								}
 | |
| 								break;
 | |
| 
 | |
| 							case USER_ACTION_REMOVE:
 | |
| 								unset($sources[$id]['Filters']['filter_conditions'][$condition['index']]);
 | |
| 								break;
 | |
| 						}
 | |
| 					}
 | |
| 					// Open Override overlay.
 | |
| 					$override_container->query('link', $override['name'])->one()->click();
 | |
| 					$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 
 | |
| 					// Get Operations Table.
 | |
| 					$operations_container = $override_overlay->getField('Operations')->asTable();
 | |
| 
 | |
| 					foreach (CTestArrayHelper::get($override, 'Operations', []) as $j => $operation) {
 | |
| 						$operation_action = CTestArrayHelper::get($operation, 'action', USER_ACTION_ADD);
 | |
| 						// Preparing reference data for Operations.
 | |
| 						switch ($operation_action) {
 | |
| 							case USER_ACTION_ADD:
 | |
| 								$temp = $operation['fields'];
 | |
| 								if (array_key_exists('Update interval', $operation)) {
 | |
| 									$temp['Update interval'] = $operation['Update interval'];
 | |
| 								}
 | |
| 								$sources[$id]['Operations'][] = $temp;
 | |
| 								break;
 | |
| 							case USER_ACTION_UPDATE:
 | |
| 								// Check if source has Operations from data to update them.
 | |
| 								foreach (CTestArrayHelper::get($operation, 'fields', []) as $key => $value) {
 | |
| 									// Skipping 'action' and 'index' fields from reference data.
 | |
| 									if (in_array($key, ['action', 'index'])) {
 | |
| 										continue;
 | |
| 									}
 | |
| 
 | |
| 									$this->assertArrayHasKey($key, $sources[$id]['Operations'][$operation['index']],
 | |
| 											'Cannot find field '.$key.' in source');
 | |
| 									$sources[$id]['Operations'][$operation['index']][$key] = $value;
 | |
| 								}
 | |
| 
 | |
| 								break;
 | |
| 							case USER_ACTION_REMOVE:
 | |
| 								unset($sources[$id]['Operations'][$operation['index']]);
 | |
| 								break;
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 			}
 | |
| 
 | |
| 			switch ($override_action) {
 | |
| 				// Perform adding or updating Override.
 | |
| 				case USER_ACTION_ADD:
 | |
| 					$override_container->query('button:Add')->one()->click();
 | |
| 					$id = null;
 | |
| 				case USER_ACTION_UPDATE:
 | |
| 					// Fill Override name and what to do if Filter matches.
 | |
| 					if (array_key_exists('fields', $override)) {
 | |
| 						$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 						$override_overlay->fill($override['fields']);
 | |
| 					}
 | |
| 					$this->fillOverrideFilter($override);
 | |
| 					$this->fillOverrideOperations($data, $override, $sources, $id);
 | |
| 					$this->checkSubmittedOverlay($data['expected'], $override_overlay,
 | |
| 							CTestArrayHelper::get($override, 'error'));
 | |
| 
 | |
| 					if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
 | |
| 						// Check that Override with correct name was added to Overrides table.
 | |
| 						$fields = (CTestArrayHelper::get($override, 'fields'))
 | |
| 							? $override['fields']['Name']
 | |
| 							: $sources[$i]['fields']['Name'];
 | |
| 						$this->assertEquals($fields, $override_container->getRow($i)->getColumn('Name')->getText());
 | |
| 						// Check that Override in table has correct processing status.
 | |
| 						$stop_processing = (CTestArrayHelper::get($override,
 | |
| 								'fields.If filter matches') === 'Stop processing') ? 'Yes' : 'No';
 | |
| 						$this->assertEquals($stop_processing, $override_container->getRow($i)->getColumn('Stop processing')
 | |
| 								->getText());
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case USER_ACTION_REMOVE:
 | |
| 					$override_container->findRow('Name', $override['name'])->query('button:Remove')->one()->click();
 | |
| 					break;
 | |
| 
 | |
| 				default:
 | |
| 					throw new Exception('Cannot perform action "'.$override_action.'".');
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
 | |
| 			// Submit LLD update.
 | |
| 			$form->submit();
 | |
| 			$this->assertMessage(TEST_GOOD, 'Discovery rule updated');
 | |
| 			$this->assertEquals(1, CDBHelper::getCount('SELECT NULL FROM items WHERE itemid ='.self::UPDATED_ID));
 | |
| 
 | |
| 			self::$created_id = self::UPDATED_ID;
 | |
| 			$this->checkSavedState(['overrides' => $sources]);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @param array         $override          override fields from data
 | |
| 	 *
 | |
| 	 * @return CFormElement $override_overlay  override or condition form in overlay
 | |
| 	 */
 | |
| 	private function fillOverrideFilter($override) {
 | |
| 		$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 
 | |
| 		// Add Filters to override.
 | |
| 		if (array_key_exists('Filters', $override)) {
 | |
| 			$filters_table = $override_overlay->query('id:overrides_filters')->asMultifieldTable()->one();
 | |
| 			$mapping = $this->setFiltersTableMapping($filters_table);
 | |
| 			$filters_table->setFieldMapping($mapping)->fill($override['Filters']['filter_conditions']);
 | |
| 
 | |
| 			// Add Type of calculation if there are more then 2 filters.
 | |
| 			if (array_key_exists('Type of calculation', $override['Filters'])) {
 | |
| 				$override_overlay->query('name:overrides_evaltype')->waitUntilPresent()->one()
 | |
| 						->asDropdown()->fill($override['Filters']['Type of calculation']);
 | |
| 
 | |
| 				// Add formula if Type of calculation is Custom.
 | |
| 				if (array_key_exists('formula', $override['Filters'])) {
 | |
| 					$override_overlay->query('id:overrides_formula')->waitUntilPresent()->one()
 | |
| 							->fill($override['Filters']['formula']);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @param array         $data              data provider
 | |
| 	 * @param array         $override          override fields from data
 | |
| 	 *
 | |
| 	 * @return CFormElement $override_overlay  override or condition form in overlay
 | |
| 	 */
 | |
| 	private function fillOverrideOperations($data, $override, $sources = null, $id = null) {
 | |
| 		$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 		$operation_container = $override_overlay->getField('Operations')->asTable();
 | |
| 
 | |
| 		// Add Operations to override.
 | |
| 		foreach(CTestArrayHelper::get($override, 'Operations', []) as $i => $operation){
 | |
| 
 | |
| 			$operation_action = CTestArrayHelper::get($operation, 'action', USER_ACTION_ADD);
 | |
| 			unset($operation['action']);
 | |
| 
 | |
| 			$row = null;
 | |
| 			switch ($operation_action) {
 | |
| 				case USER_ACTION_ADD:
 | |
| 					$row = $operation_container->getRows()->count() - 1;
 | |
| 					$operation_container->query('button:Add')->one()->click();
 | |
| 					break;
 | |
| 
 | |
| 				case USER_ACTION_UPDATE:
 | |
| 					$row = $operation['index'];
 | |
| 					$operation_container->getRow($row)->query('button:Edit')->one()->click();
 | |
| 					unset($operation['index']);
 | |
| 					break;
 | |
| 			}
 | |
| 
 | |
| 			switch ($operation_action) {
 | |
| 				case USER_ACTION_ADD:
 | |
| 				case USER_ACTION_UPDATE:
 | |
| 					$operation_overlay = $this->query('id:lldoperation_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 					if (array_key_exists('fields', $operation)) {
 | |
| 						$operation_overlay->fill($operation['fields']);
 | |
| 					}
 | |
| 
 | |
| 					// Fill Delay and Intervals.
 | |
| 					if (array_key_exists('Update interval', $operation)) {
 | |
| 						if ($operation['Update interval'] !== null) {
 | |
| 							$intervals = $operation_overlay->getField('Update interval');
 | |
| 							$operation_overlay->query('id:visible_opperiod')->one()->fill(true);
 | |
| 							if (array_key_exists('Delay', $operation['Update interval'])) {
 | |
| 								$intervals->query('id:opperiod_delay')->waitUntilVisible()->one()
 | |
| 										->fill($operation['Update interval']['Delay']);
 | |
| 							}
 | |
| 							if (array_key_exists('Custom intervals', $operation['Update interval'])) {
 | |
| 								$this->query('xpath:.//table[@id="lld_overrides_custom_intervals"]')
 | |
| 										->asMultifieldTable(['mapping' => self::INTERVAL_MAPPING])->one()
 | |
| 										->fill($operation['Update interval']['Custom intervals']);
 | |
| 							}
 | |
| 						}
 | |
| 						else {
 | |
| 							$operation_overlay->query('id:visible_opperiod')->one()->asCheckbox()->fill(false);
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					$operation_overlay->submit();
 | |
| 					$this->checkSubmittedOverlay($data['expected'], $operation_overlay,
 | |
| 							CTestArrayHelper::get($override, 'error')
 | |
| 					);
 | |
| 
 | |
| 					if (CTestArrayHelper::get($data, 'expected') === TEST_GOOD) {
 | |
| 						// Check that Operation was added to Operations table.
 | |
| 						$object = CTestArrayHelper::get($operation, 'fields.Object');
 | |
| 						if ($object === null) {
 | |
| 							$object = $sources[$id]['Operations'][$i]['Object'];
 | |
| 						}
 | |
| 
 | |
| 						$operator = CTestArrayHelper::get($operation, 'fields.Condition.operator');
 | |
| 						if ($operator === null) {
 | |
| 							$operator = $sources[$id]['Operations'][$i]['Condition']['operator'];
 | |
| 						}
 | |
| 
 | |
| 						$value = CTestArrayHelper::get($operation, 'fields.Condition.value');
 | |
| 						if ($value === null) {
 | |
| 							$value = $sources[$id]['Operations'][$i]['Condition']['value'];
 | |
| 						}
 | |
| 
 | |
| 						$condition_text = $object.' '.$operator.' '.$value;
 | |
| 						$this->assertEquals($condition_text,
 | |
| 								$operation_container->getRow($row)->getColumn('Condition')->getText()
 | |
| 						);
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case USER_ACTION_REMOVE:
 | |
| 					$condition_text = $operation['fields']['Object'].' '.
 | |
| 							$operation['fields']['Condition']['operator'].' '.
 | |
| 							$operation['fields']['Condition']['value'];
 | |
| 					$row = $operation_container->findRow('Condition', $condition_text)->query('button:Remove')->one()->click();
 | |
| 					$row->waitUntilNotPresent();
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 		// Submit Override.
 | |
| 		$override_overlay->submit();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function for checking successful/failed overlay submitting.
 | |
| 	 *
 | |
| 	 * @param string		$expected	case GOOD or BAD
 | |
| 	 * @param CFormElement	$overlay 	override or condition form in overlay
 | |
| 	 * @param string	    $error		error message text
 | |
| 	 */
 | |
| 	private function checkSubmittedOverlay($expected, $overlay, $error) {
 | |
| 		switch ($expected) {
 | |
| 			case TEST_GOOD:
 | |
| 				$overlay->waitUntilNotPresent();
 | |
| 				break;
 | |
| 			case TEST_BAD:
 | |
| 				$this->assertMessage(TEST_BAD, null, $error);
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private function checkSavedState($data) {
 | |
| 		// Skip Bad cases.
 | |
| 		if (CTestArrayHelper::get($data, 'expected') === TEST_BAD) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Open saved LLD.
 | |
| 		$this->page->login()->open('host_discovery.php?form=update&context=host&itemid='.self::$created_id);
 | |
| 		$form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
 | |
| 		$form->selectTab('Overrides');
 | |
| 		$override_container = $form->getField('Overrides')->asTable();
 | |
| 		// Get Overrides count.
 | |
| 		$overrides_count = $override_container->getRows()->count();
 | |
| 
 | |
| 		// Write Override names from data to array.
 | |
| 		foreach ($data['overrides'] as $override) {
 | |
| 			$override_names[] = $override['fields']['Name'];
 | |
| 			$stop_processing[] = (CTestArrayHelper::get($override['fields'],
 | |
| 					'If filter matches') === 'Stop processing') ? 'Yes' : 'No';
 | |
| 		}
 | |
| 
 | |
| 		// Compare Override names from table with data.
 | |
| 		for ($k = 0; $k < $overrides_count - 1; $k++) {
 | |
| 			$this->assertEquals($override_names[$k],
 | |
| 					$override_container->getRow($k)->getColumn('Name')->getText()
 | |
| 			);
 | |
| 			// Check that Override in table has correct processing status.
 | |
| 			$this->assertEquals($stop_processing[$k],
 | |
| 					$override_container->getRow($k)->getColumn('Stop processing')->getText()
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		foreach ($data['overrides'] as $override) {
 | |
| 			// Open each override dialog.
 | |
| 			$row = $override_container->findRow('Name', $override['fields']['Name']);
 | |
| 			$row->query('link', $override['fields']['Name'])->one()->click();
 | |
| 			$override_overlay = $this->query('id:lldoverride_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 
 | |
| 			// Check that Override fields filled with correct data.
 | |
| 			foreach ($override['fields'] as $field => $value) {
 | |
| 				$override_overlay->getField($field)->checkValue($value);
 | |
| 			}
 | |
| 
 | |
| 			if (array_key_exists('Filters', $override)) {
 | |
| 				foreach ($override['Filters']['filter_conditions'] as &$condition) {
 | |
| 					unset($condition['index']);
 | |
| 					unset($condition['action']);
 | |
| 				}
 | |
| 				unset($condition);
 | |
| 
 | |
| 				// Check that Filters are filled correctly.
 | |
| 				$filters_table = $override_overlay->query('id:overrides_filters')->asMultifieldTable()->one();
 | |
| 				$mapping = $this->setFiltersTableMapping($filters_table);
 | |
| 				$filters_table->setFieldMapping($mapping)->checkValue($override['Filters']['filter_conditions']);
 | |
| 
 | |
| 				// Check that Evaluation type is filled correctly.
 | |
| 				if (array_key_exists('Type of calculation', $override['Filters'])) {
 | |
| 					$evaluation_type = $override_overlay->query('name:overrides_evaltype')->one()->asDropdown()->getValue();
 | |
| 					$this->assertEquals($override['Filters']['Type of calculation'], $evaluation_type);
 | |
| 
 | |
| 					// Check that Formula is filled correctly.
 | |
| 					if (array_key_exists('formula', $override['Filters'])) {
 | |
| 						$formula = CTestArrayHelper::get($override['Filters'], 'Type of calculation') !== 'Custom expression'
 | |
| 							? $override_overlay->query('id:overrides_expression')->one()->getText()
 | |
| 							: $override_overlay->query('id:overrides_formula')->one()->getValue();
 | |
| 						$this->assertEquals($override['Filters']['formula'], $formula);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			$operation_container = $override_overlay->getField('Operations')->asTable();
 | |
| 			// Get Operations count.
 | |
| 			$operation_count = $operation_container->getRows()->count();
 | |
| 
 | |
| 			if (array_key_exists('Operations', $override)) {
 | |
| 				// Write Conditions from data to array.
 | |
| 				$condition_text = [];
 | |
| 				foreach ($override['Operations'] as $operation) {
 | |
| 					$fields = array_key_exists('fields', $operation) ? $operation['fields'] : $operation;
 | |
| 
 | |
| 					$condition_text[] = $fields['Object'].' '.
 | |
| 							$fields['Condition']['operator'].' '.
 | |
| 							$fields['Condition']['value'];
 | |
| 				}
 | |
| 
 | |
| 				// Compare Conditions from table with data.
 | |
| 				$actual_conditions = [];
 | |
| 				for ($n = 0; $n < $operation_count - 1; $n++) {
 | |
| 					$actual_conditions[] = $operation_container->getRow($n)->getColumn('Condition')->getText();
 | |
| 				}
 | |
| 				$this->assertEquals($condition_text, $actual_conditions);
 | |
| 
 | |
| 				foreach ($override['Operations'] as $i => $operation) {
 | |
| 					$operation_container->getRow($i)->query('button:Edit')->one()->click();
 | |
| 					$operation_overlay = $this->query('id:lldoperation_form')->waitUntilPresent()->asCheckboxForm()->one();
 | |
| 					$operation_overlay->checkValue(
 | |
| 							array_key_exists('fields', $operation) ? $operation['fields'] : $operation
 | |
| 					);
 | |
| 
 | |
| 					// Close Operation dialog.
 | |
| 					$operation_overlay->submit()->waitUntilNotPresent();
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// Close Override dialog.
 | |
| 			COverlayDialogElement::find()->one()->close();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function for updating the mapping of the specified Filters multi-field table.
 | |
| 	 *
 | |
| 	 * @param CMultifieldTableElement	$filters_table	table which mapping needs to be updated
 | |
| 	 *
 | |
| 	 * @return array
 | |
| 	 */
 | |
| 	private function setFiltersTableMapping($filters_table) {
 | |
| 		$mapping = $filters_table->detectFieldMapping();
 | |
| 		$mapping['Regular expression']['name'] = 'value';
 | |
| 		$mapping['Regular expression']['selector'] = 'xpath:./div/input';
 | |
| 
 | |
| 		return $mapping;
 | |
| 	}
 | |
| }
 |