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.
		
		
		
		
		
			
		
			
				
					
					
						
							1224 lines
						
					
					
						
							36 KiB
						
					
					
				
			
		
		
	
	
							1224 lines
						
					
					
						
							36 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__).'/../../include/helpers/CDataHelper.php';
 | |
| require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
 | |
| use Facebook\WebDriver\Exception\UnexpectedAlertOpenException;
 | |
| 
 | |
| /**
 | |
|  * @backup dashboard, hosts
 | |
|  *
 | |
|  * @onBefore prepareTemplateDashboardsData
 | |
|  */
 | |
| class testFormTemplateDashboards extends CWebTest {
 | |
| 
 | |
| 	const UPDATE_TEMPLATEID = 50000;	// ID of the "Template ZBX6663 First" template used for template dashboards tests.
 | |
| 	const HOST_FOR_TEMPLATE = 99015;	// ID of the "Empty host" host to which a template with dashboards will be linked.
 | |
| 
 | |
| 	protected static $dashboardid_with_widgets;
 | |
| 	protected static $empty_dashboardid;
 | |
| 	protected static $dashboardid_for_update;
 | |
| 
 | |
| 	private static $previous_widget_name = 'Widget for update';
 | |
| 
 | |
| 	/**
 | |
| 	 * Attach MessageBehavior to the test.
 | |
| 	 *
 | |
| 	 * @return array
 | |
| 	 */
 | |
| 	public function getBehaviors() {
 | |
| 		return [
 | |
| 			'class' => CMessageBehavior::class
 | |
| 		];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function creates template dashboards and defines the corresponding dashboard IDs.
 | |
| 	 */
 | |
| 	public static function prepareTemplateDashboardsData() {
 | |
| 		$response = CDataHelper::call('templatedashboard.create', [
 | |
| 			[
 | |
| 				'templateid' => self::UPDATE_TEMPLATEID,
 | |
| 				'name' => 'Dashboard with all widgets',
 | |
| 				'pages' => [
 | |
| 					[
 | |
| 						'name' => 'Page with widgets',
 | |
| 						'widgets' => [
 | |
| 							[
 | |
| 								'type' => 'clock',
 | |
| 								'name' => 'Clock widget',
 | |
| 								'width' => 4,
 | |
| 								'height' => 4
 | |
| 							],
 | |
| 							[
 | |
| 								'type' => 'graph',
 | |
| 								'name' => 'Graph (classic) widget',
 | |
| 								'x' => 4,
 | |
| 								'y' => 0,
 | |
| 								'width' => 8,
 | |
| 								'height' => 4,
 | |
| 								'fields' => [
 | |
| 									[
 | |
| 										'type' => 0,
 | |
| 										'name' => 'source_type',
 | |
| 										'value' => 1
 | |
| 									],
 | |
| 									[
 | |
| 										'type' => 4,
 | |
| 										'name' => 'itemid',
 | |
| 										'value' => 400410
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							[
 | |
| 								'type' => 'plaintext',
 | |
| 								'name' => 'Plain text widget',
 | |
| 								'x' => 12,
 | |
| 								'y' => 0,
 | |
| 								'width' => 6,
 | |
| 								'height' => 4,
 | |
| 								'fields' => [
 | |
| 									[
 | |
| 										'type' => 4,
 | |
| 										'name' => 'itemids',
 | |
| 										'value' => 400410
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							[
 | |
| 								'type' => 'url',
 | |
| 								'name' => 'URL widget',
 | |
| 								'x' => 18,
 | |
| 								'y' => 0,
 | |
| 								'width' => 6,
 | |
| 								'height' => 4,
 | |
| 								'fields' => [
 | |
| 									[
 | |
| 										'type' => 1,
 | |
| 										'name' => 'url',
 | |
| 										'value' => 'http://zabbix.com'
 | |
| 									]
 | |
| 								]
 | |
| 							],
 | |
| 							[
 | |
| 								'type' => 'graphprototype',
 | |
| 								'name' => 'Graph prototype widget',
 | |
| 								'x' => 0,
 | |
| 								'y' => 4,
 | |
| 								'width' => 12,
 | |
| 								'height' => 6,
 | |
| 								'fields' => [
 | |
| 									[
 | |
| 										'type' => 7,
 | |
| 										'name' => 'graphid',
 | |
| 										'value' => 700016
 | |
| 									]
 | |
| 								]
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				'templateid' => self::UPDATE_TEMPLATEID,
 | |
| 				'name' => 'Empty Dashboard without widgets',
 | |
| 				'pages' => [[]]
 | |
| 			],
 | |
| 			[
 | |
| 				'templateid' => self::UPDATE_TEMPLATEID,
 | |
| 				'name' => 'Dashboard for widget update',
 | |
| 				'pages' => [
 | |
| 					[
 | |
| 						'widgets' => [
 | |
| 							[
 | |
| 								'type' => 'clock',
 | |
| 								'name' => 'Widget for update',
 | |
| 								'x' => 0,
 | |
| 								'y' => 0,
 | |
| 								'width' => 4,
 | |
| 								'height' => 4
 | |
| 							],
 | |
| 							[
 | |
| 								'type' => 'clock',
 | |
| 								'name' => 'Widget 4 duplicate check',
 | |
| 								'x' => 4,
 | |
| 								'y' => 0,
 | |
| 								'width' => 4,
 | |
| 								'height' => 4
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			]
 | |
| 		]);
 | |
| 
 | |
| 		self::$dashboardid_with_widgets = $response['dashboardids'][0];
 | |
| 		self::$empty_dashboardid = $response['dashboardids'][1];
 | |
| 		self::$dashboardid_for_update = $response['dashboardids'][2];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that links the template with dashboards to "Empty host" host.
 | |
| 	 */
 | |
| 	public static function prepareHostLinkageToTemplateData() {
 | |
| 		CDataHelper::call('host.update', [
 | |
| 			'hostid' => self::HOST_FOR_TEMPLATE,
 | |
| 			'templates' => [
 | |
| 				[
 | |
| 					'templateid' => self::UPDATE_TEMPLATEID
 | |
| 				]
 | |
| 			]
 | |
| 		]);
 | |
| 	}
 | |
| 
 | |
| 	public function testFormTemplateDashboards_Layout() {
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.list&templateid='.self::UPDATE_TEMPLATEID);
 | |
| 		$this->query('button:Create dashboard')->one()->click();
 | |
| 		$this->checkDialogue('Dashboard properties');
 | |
| 
 | |
| 		// Check the default new dashboard state (title, empty, editable).
 | |
| 		$dashboard = CDashboardElement::find()->asDashboard()->one()->waitUntilVisible();
 | |
| 		$this->assertEquals('Dashboards', $dashboard->getTitle());
 | |
| 		$this->assertTrue($dashboard->isEditable());
 | |
| 		$this->assertTrue($dashboard->isEmpty());
 | |
| 
 | |
| 		$controls = $dashboard->getControls();
 | |
| 		$control_buttons = [
 | |
| 			'id:dashboard-config',		// Dashboard properties menu icon.
 | |
| 			'button:Add',				// Add widget menu button.
 | |
| 			'id:dashboard-add',			// Dashboard actions chevron.
 | |
| 			'button:Save changes',		// Save changes button.
 | |
| 			'link:Cancel'				// Cancel button.
 | |
| 		];
 | |
| 
 | |
| 		// Check dashboard controls and their corresponding actions.
 | |
| 		foreach ($control_buttons as $selector) {
 | |
| 			$this->assertTrue($controls->query($selector)->one(false)->isValid());
 | |
| 
 | |
| 			switch ($selector) {
 | |
| 				case 'id:dashboard-config':
 | |
| 					$controls->query($selector)->waitUntilClickable()->one()->click();
 | |
| 					$this->checkDialogue('Dashboard properties');
 | |
| 					break;
 | |
| 
 | |
| 				case 'id:dashboard-add':
 | |
| 					$reference_items = [
 | |
| 						'Add widget' => true,
 | |
| 						'Add page' => true,
 | |
| 						'Paste widget' => false,
 | |
| 						'Paste page' => false
 | |
| 					];
 | |
| 					$controls->query($selector)->one()->click();
 | |
| 					$this->checkPopup($reference_items);
 | |
| 					break;
 | |
| 
 | |
| 				case 'button:Add':
 | |
| 					$controls->query($selector)->one()->click();
 | |
| 					$this->checkDialogue('Add widget');
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Check breadcrumbs.
 | |
| 		foreach (['Hierarchy', 'Content menu'] as $aria_label) {
 | |
| 			$this->assertTrue($this->query('xpath://ul[@aria-label='.zbx_dbstr($aria_label).']')->one()->isClickable());
 | |
| 		}
 | |
| 
 | |
| 		// Check the page title and its corresponding actions.
 | |
| 		$this->assertEquals(1, $this->query('class:sortable-item')->all()->count());
 | |
| 		$page_button = $this->query('class:selected-tab')->one();
 | |
| 		$this->assertEquals('Page 1', $page_button->getText());
 | |
| 		$page_button->query('xpath:./button')->one()->forceClick();
 | |
| 		$page_popup_items = [
 | |
| 			'Copy' => true,
 | |
| 			'Delete' => false,
 | |
| 			'Properties' => true
 | |
| 		];
 | |
| 		$this->checkPopup($page_popup_items, 'ACTIONS');
 | |
| 
 | |
| 		// Close the dashboard and corresponding popups so that the next scenario would start without alerts.
 | |
| 		$this->closeDialogue();
 | |
| 	}
 | |
| 
 | |
| 	public static function getWidgetLayoutData() {
 | |
| 		return [
 | |
| 			[
 | |
| 				[
 | |
| 					'type' => 'Clock',
 | |
| 					'fields' => [
 | |
| 						[
 | |
| 							'name' => 'Name',
 | |
| 							'attributes' => [
 | |
| 								'placeholder' => 'default',
 | |
| 								'maxlength' => 255
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Time type',
 | |
| 							'type' => 'dropdown',
 | |
| 							'possible_values' => ['Local time', 'Server time', 'Host time'],
 | |
| 							'value' => 'Local time'
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'type' => CFormElement::RELOADABLE_FILL('Graph (classic)'),
 | |
| 					'fields' => [
 | |
| 						[
 | |
| 							'name' => 'Name',
 | |
| 							'attributes' => [
 | |
| 								'placeholder' => 'default',
 | |
| 								'maxlength' => 255
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Source',
 | |
| 							'type' => 'radio_button',
 | |
| 							'possible_values' => ['Graph', 'Simple graph'],
 | |
| 							'value' => 'Graph'
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Graph',
 | |
| 							'type' => 'multiselect'
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Show legend',
 | |
| 							'type' => 'checkbox',
 | |
| 							'value' => true
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 
 | |
| 					'type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 					'fields' => [
 | |
| 						[
 | |
| 							'name' => 'Name',
 | |
| 							'attributes' => [
 | |
| 								'placeholder' => 'default',
 | |
| 								'maxlength' => 255
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Source',
 | |
| 							'type' => 'radio_button',
 | |
| 							'possible_values' => ['Graph prototype', 'Simple graph prototype'],
 | |
| 							'value' => 'Graph prototype'
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Graph prototype',
 | |
| 							'type' => 'multiselect'
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Show legend',
 | |
| 							'type' => 'checkbox',
 | |
| 							'value' => true
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Columns',
 | |
| 							'value' => 2,
 | |
| 							'attributes' => [
 | |
| 								'maxlength' => 2
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Rows',
 | |
| 							'value' => 1,
 | |
| 							'attributes' => [
 | |
| 								'maxlength' => 2
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 					'fields' => [
 | |
| 						[
 | |
| 							'name' => 'Name',
 | |
| 							'attributes' => [
 | |
| 								'placeholder' => 'default',
 | |
| 								'maxlength' => 255
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Items',
 | |
| 							'type' => 'multiselect'
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Items location',
 | |
| 							'type' => 'radio_button',
 | |
| 							'possible_values' => ['Left', 'Top'],
 | |
| 							'value' => 'Left'
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Show lines',
 | |
| 							'value' => 25,
 | |
| 							'attributes' => [
 | |
| 								'maxlength' => 3
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'Show text as HTML',
 | |
| 							'type' => 'checkbox',
 | |
| 							'value' => false
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'type' => CFormElement::RELOADABLE_FILL('URL'),
 | |
| 					'fields' => [
 | |
| 						[
 | |
| 							'name' => 'Name',
 | |
| 							'attributes' => [
 | |
| 								'placeholder' => 'default',
 | |
| 								'maxlength' => 255
 | |
| 							]
 | |
| 						],
 | |
| 						[
 | |
| 							'name' => 'URL',
 | |
| 							'attributes' => [
 | |
| 								'maxlength' => 2048
 | |
| 							]
 | |
| 						]
 | |
| 					]
 | |
| 				]
 | |
| 			]
 | |
| 		];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks the layout and the default settings of widget configuration forms.
 | |
| 	 *
 | |
| 	 * @dataProvider getWidgetLayoutData
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_WidgetDefaultLayout($data) {
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.list&templateid='.self::UPDATE_TEMPLATEID);
 | |
| 		$this->query('button:Create dashboard')->one()->click();
 | |
| 		COverlayDialogElement::find()->one()->waitUntilVisible()->close();
 | |
| 
 | |
| 		// Select the required type of widget.
 | |
| 		$this->query('button:Add')->one()->waitUntilClickable()->click();
 | |
| 		$widget_dialog = COverlayDialogElement::find()->asForm()->one()->waitUntilReady();
 | |
| 		$widget_dialog->fill(['Type' => $data['type']]);
 | |
| 		COverlayDialogElement::find()->waitUntilReady();
 | |
| 
 | |
| 		// Check form fields and their attributes based on field type.
 | |
| 		foreach ($data['fields'] as $field_details) {
 | |
| 			$field = $widget_dialog->getField($field_details['name']);
 | |
| 			$default_value = CTestArrayHelper::get($field_details, 'value', '');
 | |
| 
 | |
| 			switch (CTestArrayHelper::get($field_details, 'type', 'input')) {
 | |
| 				case 'input':
 | |
| 				case 'checkbox':
 | |
| 					$this->assertEquals($default_value, $field->getValue());
 | |
| 					if (array_key_exists('attributes', $field_details)) {
 | |
| 						foreach ($field_details['attributes'] as $attribute => $value) {
 | |
| 							$this->assertEquals($value, $field->getAttribute($attribute));
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 
 | |
| 				case 'multiselect':
 | |
| 					$default_value = '';
 | |
| 					$this->assertEquals($default_value, $field->getValue());
 | |
| 					$this->assertEquals('type here to search', $field->query('xpath:.//input')->one()->getAttribute('placeholder'));
 | |
| 					break;
 | |
| 
 | |
| 				case 'dropdown':
 | |
| 					$this->assertEquals($default_value, $field->getValue());
 | |
| 					$this->assertEquals($field_details['possible_values'], $field->getOptions()->asText());
 | |
| 					break;
 | |
| 
 | |
| 				case 'radio_button':
 | |
| 					$this->assertEquals($default_value, $field->getValue());
 | |
| 					$this->assertEquals($field_details['possible_values'], $field->getLabels()->asText());
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 		$this->assertTrue($widget_dialog->getField('Show header')->getValue());
 | |
| 
 | |
| 		// Close editing dashboard so that next test case would not fail with "Unexpected alert" error.
 | |
| 		$this->closeDialogue();
 | |
| 	}
 | |
| 
 | |
| 	public static function getDashboardPropertiesData() {
 | |
| 		return [
 | |
| 			[
 | |
| 				[
 | |
| 					'dashboard_properties' => [
 | |
| 						'Name' => 'Empty dashboard'
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'dashboard_properties' => [
 | |
| 						'Name' => ''
 | |
| 					],
 | |
| 					'error_message' => 'Incorrect value for field "name": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'dashboard_properties' => [
 | |
| 						'Name' => '   '
 | |
| 					],
 | |
| 					'error_message' => 'Incorrect value for field "name": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'dashboard_properties' => [
 | |
| 						'Name' => 'Empty Dashboard without widgets'
 | |
| 					],
 | |
| 					'error_message' => 'Dashboard "Empty Dashboard without widgets" already exists.',
 | |
| 					'check_save' => true
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'dashboard_properties' => [
 | |
| 						'Name' => '!@#$%^&*()_+=-09[]{};:\'"',
 | |
| 						'Default page display period' => '10 seconds',
 | |
| 						'Start slideshow automatically' => true
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			[
 | |
| 				[
 | |
| 					'dashboard_properties' => [
 | |
| 						'Name' => '    Trailing & leading spaces    ',
 | |
| 						'Start slideshow automatically' => false
 | |
| 					],
 | |
| 					'trim' => 'Name'
 | |
| 				]
 | |
| 			]
 | |
| 		];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks validation of the Dashboard properties overlay dialog when creating a dashboard.
 | |
| 	 *
 | |
| 	 * @backupOnce dashboard
 | |
| 	 *
 | |
| 	 * @dataProvider getDashboardPropertiesData
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_DashboardPropertiesCreate($data) {
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.list&templateid='.self::UPDATE_TEMPLATEID);
 | |
| 		$this->query('button:Create dashboard')->one()->click();
 | |
| 		$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
 | |
| 
 | |
| 		$form->fill($data['dashboard_properties']);
 | |
| 		$old_values = $form->getFields()->filter(new CElementFilter(CElementFilter::VISIBLE))->asValues();
 | |
| 		$form->submit();
 | |
| 
 | |
| 		$this->checkSettings($data, $old_values);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks validation of Dashboard properties overlay dialog update operations.
 | |
| 	 *
 | |
| 	 * @backupOnce dashboard
 | |
| 	 *
 | |
| 	 * @dataProvider getDashboardPropertiesData
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_DashboardPropertiesUpdate($data) {
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.edit&dashboardid='.self::$dashboardid_with_widgets);
 | |
| 		$this->query('id:dashboard-config')->one()->waitUntilClickable()->click();
 | |
| 		$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
 | |
| 
 | |
| 		$form->fill($data['dashboard_properties']);
 | |
| 		$old_values = $form->getFields()->filter(new CElementFilter(CElementFilter::VISIBLE))->asValues();
 | |
| 		$form->submit();
 | |
| 
 | |
| 		$this->checkSettings($data, $old_values, 'updated');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks that no changes occur after saving a template dashboard without changes.
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_SimpleUpdate() {
 | |
| 		$sql = 'SELECT * FROM widget w INNER JOIN dashboard_page dp ON dp.dashboard_pageid=w.dashboard_pageid '.
 | |
| 				'INNER JOIN dashboard d ON d.dashboardid=dp.dashboardid ORDER BY w.widgetid';
 | |
| 		$old_hash = CDBHelper::getHash($sql);
 | |
| 
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.edit&dashboardid='.self::$dashboardid_with_widgets);
 | |
| 		$this->query('button:Save changes')->one()->waitUntilClickable()->click();
 | |
| 
 | |
| 		$this->assertMessage(TEST_GOOD, 'Dashboard updated');
 | |
| 		$this->assertEquals($old_hash, CDBHelper::getHash($sql));
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks that no changes occur after cancelling a template dashboard update.
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_Cancel() {
 | |
| 		$sql = 'SELECT * FROM widget w INNER JOIN dashboard_page dp ON dp.dashboard_pageid=w.dashboard_pageid '.
 | |
| 				'INNER JOIN dashboard d ON d.dashboardid=dp.dashboardid ORDER BY w.widgetid';
 | |
| 		$old_hash = CDBHelper::getHash($sql);
 | |
| 		$fields = [
 | |
| 			'Name' => 'Cancel dashboard update',
 | |
| 			'Default page display period' => '10 minutes',
 | |
| 			'Start slideshow automatically' => false
 | |
| 		];
 | |
| 
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.edit&dashboardid='.self::$dashboardid_with_widgets);
 | |
| 		$this->query('id:dashboard-config')->one()->waitUntilClickable()->click();
 | |
| 		$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
 | |
| 		$form->fill($fields);
 | |
| 		$form->submit();
 | |
| 
 | |
| 		$this->query('link:Cancel')->one()->waitUntilClickable()->click();
 | |
| 		$this->assertEquals($old_hash, CDBHelper::getHash($sql));
 | |
| 	}
 | |
| 
 | |
| 	public static function getWidgetsCreateData() {
 | |
| 		return [
 | |
| 			// Renaming a widget
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => 'Change widget name'
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Two identical widgets
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => 'Widget 4 duplicate check'
 | |
| 					],
 | |
| 					'duplicate widget' => true
 | |
| 				]
 | |
| 			],
 | |
| 			// Clock widget with no name
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => ''
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Change time type to Server time
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => 'Clock widget server time',
 | |
| 						'Time type' => CFormElement::RELOADABLE_FILL('Server time')
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Change time type to Host time and leave item empty
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => 'Clock widget with Host time no item',
 | |
| 						'Time type' => CFormElement::RELOADABLE_FILL('Host time')
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Item": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Change time type to Host time and specify item
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => 'Clock widget with Host time',
 | |
| 						'Time type' => CFormElement::RELOADABLE_FILL('Host time'),
 | |
| 						'Item' => 'Item ZBX6663 Second'
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Widget with trailing and leading spaces in name
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Clock'),
 | |
| 						'Name' => '    Clock widget with trailing and leading spaces    '
 | |
| 					],
 | |
| 					'trim' => 'Name'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph Classic widget with missing graph
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph (classic)'),
 | |
| 						'Name' => 'Graph widget with empty graph',
 | |
| 						'Source' => 'Graph',
 | |
| 						'Graph' => []
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Graph": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph Classic widget with missing item
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph (classic)'),
 | |
| 						'Name' => 'Graph widget with empty item',
 | |
| 						'Source' => CFormElement::RELOADABLE_FILL('Simple graph'),
 | |
| 						'Item' => []
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Item": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph Classic widget with graph and legend
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph (classic)'),
 | |
| 						'Name' => 'Graph widget with graph and legend',
 | |
| 						'Source' => 'Graph',
 | |
| 						'Graph' => ['Graph ZBX6663 Second'],
 | |
| 						'Show legend' => true
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph Classic widget with Simple graph and without legend
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph (classic)'),
 | |
| 						'Name' => 'Simple graph without legend',
 | |
| 						'Source' => CFormElement::RELOADABLE_FILL('Simple graph'),
 | |
| 						'Item' => ['Item ZBX6663 Second'],
 | |
| 						'Show legend' => false
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with missing graph prototype
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with empty graph',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => []
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Graph prototype": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with missing item prototype
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with empty item prototype',
 | |
| 						'Source' => CFormElement::RELOADABLE_FILL('Simple graph prototype'),
 | |
| 						'Item prototype' => []
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Item prototype": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with empty Columns parameter
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with empty Columns (dropped to 0)',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Columns' => ''
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Columns": value must be one of 1-24.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with too high number of Columns
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with too much Columns',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Columns' => 55
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Columns": value must be one of 1-24.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with negative number of Columns
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with too much Columns',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Columns' => '-5'
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Columns": value must be one of 1-24.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with missing number of Rows
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with missing Rows (dropped to 0)',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Rows' => ''
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Rows": value must be one of 1-16.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with number of Rows too high
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with too much rows',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Rows' => 55
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Rows": value must be one of 1-16.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with negative number of Rows
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget with too much rows',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Rows' => '-5'
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Rows": value must be one of 1-16.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with graph prototype, legend, 2 rows and 2 columns
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Graph prototype widget legend',
 | |
| 						'Source' => 'Graph prototype',
 | |
| 						'Graph prototype' => ['GraphPrototype ZBX6663 Second'],
 | |
| 						'Show legend' => true,
 | |
| 						'Columns' => 2,
 | |
| 						'Rows' => 2
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Graph prototype widget with simple graph prototype, without legend, 2 row and 2 column
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Graph prototype'),
 | |
| 						'Name' => 'Simple Graph prototype without legend',
 | |
| 						'Source' => CFormElement::RELOADABLE_FILL('Simple graph prototype'),
 | |
| 						'Item prototype' => ['ItemProto ZBX6663 Second'],
 | |
| 						'Show legend' => false,
 | |
| 						'Columns' => 1,
 | |
| 						'Rows' => 1
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Plain text widget with empty Items parameter
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 						'Name' => 'Plain text widget with empty Items',
 | |
| 						'Items' => []
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Items": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Plain text widget with empty Show lines parameter (reset to 0)
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 						'Name' => 'Plain text widget with empty Show lines',
 | |
| 						'Items' => ['Item ZBX6663 Second'],
 | |
| 						'Show lines' => ''
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Show lines": value must be one of 1-100.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Plain text widget with too high value of Show lines parameter
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 						'Name' => 'Plain text widget with too much lines',
 | |
| 						'Items' => ['Item ZBX6663 Second'],
 | |
| 						'Show lines' => 999
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Show lines": value must be one of 1-100.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Plain text widget with negative Show lines parameter
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 						'Name' => 'Plain text widget with negative Show lines',
 | |
| 						'Items' => ['Item ZBX6663 Second'],
 | |
| 						'Show lines' => '-9'
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "Show lines": value must be one of 1-100.'
 | |
| 				]
 | |
| 			],
 | |
| 			// Plain text widget with Items location = top and text shown as HTML
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 						'Name' => 'Plain text widget top location HTML',
 | |
| 						'Items' => ['Item ZBX6663 Second'],
 | |
| 						'Show lines' => 9,
 | |
| 						'Items location' => 'Top',
 | |
| 						'Show text as HTML' => true
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// Plain text widget with Items location = left and text shown as plain text
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('Plain text'),
 | |
| 						'Name' => 'Plain text widget left location no HTML',
 | |
| 						'Items' => ['Item ZBX6663 Second'],
 | |
| 						'Show lines' => 9,
 | |
| 						'Items location' => 'Left',
 | |
| 						'Show text as HTML' => false
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// URL widget with empty URL
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('URL'),
 | |
| 						'Name' => 'URL widget with empty URL'
 | |
| 					],
 | |
| 					'error_message' => 'Invalid parameter "URL": cannot be empty.'
 | |
| 				]
 | |
| 			],
 | |
| 			// URL widget with incorrect URL
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('URL'),
 | |
| 						'Name' => 'URL widget with text URL',
 | |
| 						'URL' => 'home_sweet_home'
 | |
| 					]
 | |
| 				]
 | |
| 			],
 | |
| 			// URL widget with trailing and leading spaces in URL
 | |
| 			[
 | |
| 				[
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('URL'),
 | |
| 						'Name' => 'URL widget with trailing and leading spaces in URL',
 | |
| 						'URL' => '    URL    '
 | |
| 					],
 | |
| 					'trim' => 'URL'
 | |
| 				]
 | |
| 			],
 | |
| 			// URL widget with spaces in URL
 | |
| 			[
 | |
| 				[
 | |
| 					'expected' => TEST_BAD,
 | |
| 					'fields' => [
 | |
| 						'Type' => CFormElement::RELOADABLE_FILL('URL'),
 | |
| 						'Name' => 'URL widget with space in URL',
 | |
| 						'URL' => '     '
 | |
| 					],
 | |
| 					'trim' => 'URL',
 | |
| 					'error_message' => 'Invalid parameter "URL": cannot be empty.'
 | |
| 				]
 | |
| 			]
 | |
| 		];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that validates the Widget configuration form for a template dashboard.
 | |
| 	 *
 | |
| 	 * @dataProvider getWidgetsCreateData
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_CreateWidget($data) {
 | |
| 		try {
 | |
| 			$this->page->login()->open('zabbix.php?action=template.dashboard.edit&dashboardid='.self::$empty_dashboardid);
 | |
| 		}
 | |
| 		catch (UnexpectedAlertOpenException $e) {
 | |
| 			// Sometimes previous test leaves dashboard edit page open.
 | |
| 			$this->page->acceptAlert();
 | |
| 			$this->page->login()->open('zabbix.php?action=template.dashboard.edit&dashboardid='.self::$empty_dashboardid);
 | |
| 		}
 | |
| 
 | |
| 		$this->query('button:Add')->one()->waitUntilClickable()->click();
 | |
| 		$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
 | |
| 		$form->fill($data['fields']);
 | |
| 
 | |
| 		// Trimming is only triggered together with an on-change event which is generated once focus is removed.
 | |
| 		$this->page->removeFocus();
 | |
| 		$old_values = $form->getFields()->filter(new CElementFilter(CElementFilter::VISIBLE))->asValues();
 | |
| 		$form->submit();
 | |
| 
 | |
| 		// In case of the scenario with identical widgets the same widget needs to be added once again.
 | |
| 		if (array_key_exists('duplicate widget', $data)) {
 | |
| 			$this->query('button:Add')->one()->waitUntilClickable()->click();
 | |
| 			$form->invalidate();
 | |
| 			$form->fill($data['fields']);
 | |
| 			$this->page->removeFocus();
 | |
| 			$form->submit();
 | |
| 		}
 | |
| 
 | |
| 		$this->checkSettings($data, $old_values, 'updated', 'widget create');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks update of template dashboards widgets parameters.
 | |
| 	 *
 | |
| 	 * @dataProvider getWidgetsCreateData
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_UpdateWidget($data) {
 | |
| 		$this->page->login()->open('zabbix.php?action=template.dashboard.edit&dashboardid='.self::$dashboardid_for_update);
 | |
| 
 | |
| 		$form = CDashboardElement::find()->one()->getWidget(self::$previous_widget_name)->edit();
 | |
| 		COverlayDialogElement::find()->waitUntilReady();
 | |
| 		$form->fill($data['fields']);
 | |
| 		$this->page->removeFocus();
 | |
| 		COverlayDialogElement::find()->waitUntilReady();
 | |
| 		$old_values = $form->getFields()->filter(new CElementFilter(CElementFilter::VISIBLE))->asValues();
 | |
| 		$form->submit();
 | |
| 
 | |
| 		$this->checkSettings($data, $old_values, 'updated', 'widget update');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks the layout of a template dashboard with widgets from monitoring hosts view.
 | |
| 	 * The ignore browser errors annotation is required due to the errors coming from the URL opened in the URL widget.
 | |
| 	 *
 | |
| 	 * @ignoreBrowserErrors
 | |
| 	 *
 | |
| 	 * @onBefore prepareHostLinkageToTemplateData
 | |
| 	 */
 | |
| 	public function testFormTemplateDashboards_ViewDashboardOnHost() {
 | |
| 		$this->page->login()->open('zabbix.php?action=host.dashboard.view&hostid='.self::HOST_FOR_TEMPLATE);
 | |
| 		$this->page->waitUntilReady();
 | |
| 		$this->query('xpath://button[@title="Dashboard list"]')->asPopupButton()->one()
 | |
| 				->select('Dashboard with all widgets');
 | |
| 
 | |
| 		$skip_selectors = [
 | |
| 			'class:clock',
 | |
| 			'class:flickerfreescreen',
 | |
| 			'class:widget-url',
 | |
| 			'xpath://footer'
 | |
| 		];
 | |
| 		$skip_elements = [];
 | |
| 
 | |
| 		foreach ($skip_selectors as $identifier) {
 | |
| 			$skip_elements[] = $this->query($identifier)->waitUntilVisible()->one();
 | |
| 		}
 | |
| 
 | |
| 		$this->assertScreenshotExcept(null, $skip_elements, 'dashboard_on_host');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Functions that checks the layout of the "Dashboard properties" and "Add widget" overlay dialogs.
 | |
| 	 *
 | |
| 	 * @param string	$title	The title of the overlay dialog.
 | |
| 	 */
 | |
| 	private function checkDialogue($title) {
 | |
| 		if ($title === 'Dashboard properties') {
 | |
| 			$parameters = [
 | |
| 				'Name' => 'New dashboard',
 | |
| 				'Default page display period' => '30 seconds',
 | |
| 				'Start slideshow automatically' => true
 | |
| 			];
 | |
| 			$buttons = ['Apply', 'Cancel'];
 | |
| 			$display_periods = ['10 seconds', '30 seconds', '1 minute', '2 minutes', '10 minutes', '30 minutes', '1 hour'];
 | |
| 		}
 | |
| 		else {
 | |
| 			$parameters = [
 | |
| 				'Show header' => true
 | |
| 			];
 | |
| 			$buttons = ['Add', 'Cancel'];
 | |
| 		}
 | |
| 
 | |
| 		$dialog = COverlayDialogElement::find()->waitUntilReady()->one();
 | |
| 		$form = $dialog->asForm();
 | |
| 		$this->assertEquals($title, $dialog->getTitle());
 | |
| 
 | |
| 		$this->assertEquals(2, $dialog->getFooter()->query('button', $buttons)->all()
 | |
| 				->filter(new CElementFilter(CElementFilter::CLICKABLE))->count()
 | |
| 		);
 | |
| 
 | |
| 		foreach ($parameters as $name => $value) {
 | |
| 			$this->assertEquals($value, $form->getField($name)->getValue());
 | |
| 		}
 | |
| 
 | |
| 		if ($title === 'Dashboard properties') {
 | |
| 			$this->assertEquals($display_periods, $form->getField('Default page display period')->getOptions()->asText());
 | |
| 		}
 | |
| 		else {
 | |
| 			$all_types = ['Action log', 'Clock', 'Discovery status', 'Favorite graphs', 'Favorite maps', 'Gauge', 'Geomap',
 | |
| 					'Graph', 'Graph (classic)', 'Graph prototype', 'Host availability', 'Item value', 'Map',
 | |
| 					'Map navigation tree', 'Plain text', 'Problem hosts', 'Problems', 'Problems by severity', 'SLA report',
 | |
| 					'System information', 'Top hosts', 'Top triggers', 'Trigger overview', 'URL', 'Web monitoring', 'Data overview'
 | |
| 			];
 | |
| 			$this->assertEquals($all_types, $form->getField('Type')->getOptions()->asText());
 | |
| 		}
 | |
| 		$dialog->close();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks the content of popup menu elements on a template dashboard.
 | |
| 	 *
 | |
| 	 * @param array		$items	An array of items and their states in a popup menu.
 | |
| 	 * @param string	$title	The title of the popup menu.
 | |
| 	 */
 | |
| 	private function checkPopup($items, $title = false) {
 | |
| 		$popup = CPopupMenuElement::find()->one()->waitUntilVisible();
 | |
| 
 | |
| 		foreach ($items as $item => $enabled) {
 | |
| 			$this->assertTrue($popup->getItem($item)->isEnabled($enabled));
 | |
| 		}
 | |
| 
 | |
| 		if ($title) {
 | |
| 			$this->assertEquals([$title], $popup->getTitles()->asText());
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that closes an overlay dialog and alert on a template dashboard before proceeding to the next test.
 | |
| 	 */
 | |
| 	private function closeDialogue() {
 | |
| 		$overlay = COverlayDialogElement::find()->one(false);
 | |
| 		if ($overlay->isValid()) {
 | |
| 			$overlay->close();
 | |
| 		}
 | |
| 		$this->query('link:Cancel')->one()->forceClick();
 | |
| 
 | |
| 		if ($this->page->isAlertPresent()) {
 | |
| 			$this->page->acceptAlert();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Function that checks the previously saved dashboard settings form.
 | |
| 	 *
 | |
| 	 * @param array		$data			Data provider.
 | |
| 	 * @param array		$old_values		Values obtained from the configuration form before saving the dashboard.
 | |
| 	 * @param string	$status			Expected successful action that was made to the dashboard after saving it.
 | |
| 	 * @param string	$check			Action that should be checked.
 | |
| 	 */
 | |
| 	private function checkSettings($data, $old_values, $status = 'created', $check = 'dashboard action') {
 | |
| 		if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_BAD) {
 | |
| 			if (CTestArrayHelper::get($data, 'check_save')) {
 | |
| 				$this->query('button:Save changes')->one()->click();
 | |
| 			}
 | |
| 			else {
 | |
| 				if (array_key_exists('trim', $data)) {
 | |
| 					$old_values[$data['trim']] = trim($old_values[$data['trim']]);
 | |
| 				}
 | |
| 				$form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
 | |
| 				$this->assertEquals($old_values, $form->getFields()->filter(new CElementFilter(CElementFilter::VISIBLE))->asValues());
 | |
| 			}
 | |
| 			$this->assertMessage(TEST_BAD, null, $data['error_message']);
 | |
| 			$this->closeDialogue();
 | |
| 		}
 | |
| 		else {
 | |
| 			COverlayDialogElement::ensureNotPresent();
 | |
| 			// Wait for widgets to be present as dashboard is slow when there ame many widgets on it.
 | |
| 			if ($check !== 'dashboard action') {
 | |
| 				if (CTestArrayHelper::get($data, 'trim') === 'Name') {
 | |
| 					$data['fields']['Name'] = trim($data['fields']['Name']);
 | |
| 				}
 | |
| 				$name = ($data['fields']['Name'] === '') ? 'Local' : $data['fields']['Name'];
 | |
| 				CDashboardElement::find()->waitUntilReady()->one()->getWidget($name);
 | |
| 			}
 | |
| 			$this->query('button:Save changes')->one()->click();
 | |
| 
 | |
| 			$this->page->waitUntilReady();
 | |
| 			$this->assertMessage(TEST_GOOD, 'Dashboard '.$status);
 | |
| 
 | |
| 			// In case of successful widget update rewrite the widget name to be updated for the next scenario.
 | |
| 			if ($check === 'widget update') {
 | |
| 				self::$previous_widget_name = $name;
 | |
| 			}
 | |
| 
 | |
| 			// Trim trailing and leading spaces from reference dashboard name if necessary.
 | |
| 			$created_values = $old_values;
 | |
| 			if (array_key_exists('trim', $data)) {
 | |
| 				$created_values[$data['trim']] = trim($created_values[$data['trim']]);
 | |
| 			}
 | |
| 
 | |
| 			$dashboard_name = ($check === 'dashboard action')
 | |
| 					? $created_values['Name']
 | |
| 					: (($check === 'widget create') ? 'Empty Dashboard without widgets' : 'Dashboard for widget update');
 | |
| 			$this->query('link', $dashboard_name)->one()->waitUntilClickable()->click();
 | |
| 			$this->page->waitUntilReady();
 | |
| 
 | |
| 			if ($check !== 'dashboard action') {
 | |
| 				$reopened_form = CDashboardElement::find()->waitUntilReady()->one()->getWidget($name)->edit();
 | |
| 			}
 | |
| 			else {
 | |
| 				$this->query('id:dashboard-config')->one()->click();
 | |
| 				$reopened_form = COverlayDialogElement::find()->asForm()->one()->waitUntilVisible();
 | |
| 			}
 | |
| 
 | |
| 			$this->assertEquals($created_values, $reopened_form->getFields()->filter(new CElementFilter(CElementFilter::VISIBLE))->asValues());
 | |
| 
 | |
| 			$this->closeDialogue();
 | |
| 		}
 | |
| 	}
 | |
| }
 |