<?php /* ** Zabbix ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU 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'; require_once dirname(__FILE__).'/../behaviors/CTableBehavior.php'; require_once dirname(__FILE__).'/../behaviors/CTagBehavior.php'; require_once dirname(__FILE__).'/../../include/helpers/CDataHelper.php'; /** * @backup widget, profiles, triggers, problem, config * * @onBefore prepareData */ class testDashboardTriggerOverviewWidget extends CWebTest { /** * Attach MessageBehavior, TableBehavior and TagBehavior to the test. */ public function getBehaviors() { return [ CMessageBehavior::class, CTableBehavior::class, [ 'class' => CTagBehavior::class, 'tag_selector' => 'id:tags_table_tags' ] ]; } private static $dashboardid; private static $create_page = 'Page for creation'; private static $update_widget = 'Trigger overview for reference'; private static $delete_widget = 'Trigger overview for delete'; private static $resolved_trigger = '1_trigger_Average'; private static $dependency_trigger = 'Trigger disabled with tags'; private static $icon_host = 'Host for triggers filtering'; private static $background_classes = [ '1_trigger_Average' => 'normal-bg cursor-pointer blink', '1_trigger_Disaster' => 'disaster-bg', '1_trigger_High' => 'high-bg', '1_trigger_Not_classified' => 'na-bg', '1_trigger_Warning' => 'warning-bg', '2_trigger_Information' => 'info-bg', '3_trigger_Average' => 'average-bg', 'Trigger_for_suppression' => 'average-bg', '4_trigger_Average' => 'average-bg', 'Inheritance trigger with tags' => 'average-bg', '3_trigger_Disaster' => 'normal-bg', 'Dependent trigger ONE' => 'normal-bg', 'Discovered trigger one' => 'normal-bg', 'Trigger disabled with tags' => 'normal-bg' ]; private static $trigger_icons = [ '2_trigger_Information' => 'icon-ackn', '3_trigger_Average' => 'icon-ackn', '4_trigger_Average' => 'icon-ackn', 'Dependent trigger ONE' => 'icon-depend-down', 'Inheritance trigger with tags' => 'icon-depend-down', 'Trigger disabled with tags' => 'icon-depend-up' ]; /** * SQL query to get widget and widget_field tables to compare hash values, but without widget_fieldid * because it can change. */ private $sql = 'SELECT wf.widgetid, wf.type, wf.name, wf.value_int, wf.value_str, wf.value_groupid, wf.value_hostid,'. ' wf.value_itemid, wf.value_graphid, wf.value_sysmapid, w.widgetid, w.dashboard_pageid, w.type, w.name, w.x, w.y,'. ' w.width, w.height'. ' FROM widget_field wf'. ' INNER JOIN widget w'. ' ON w.widgetid=wf.widgetid ORDER BY wf.widgetid, wf.name, wf.value_int, wf.value_str, wf.value_groupid, wf.value_hostid,'. ' wf.value_itemid, wf.value_graphid'; /** * Function creates dashboards with widgets and adjusts trigger and problems config for the test. */ public static function prepareData() { $response = CDataHelper::call('dashboard.create', [ [ 'name' => 'Dashboard for Trigger overview widgets', 'private' => 0, 'auto_start' => 0, 'pages' => [ [ 'name' => 'Page with widgets', 'widgets' => [ [ 'type' => 'trigover', 'name' => self::$update_widget, 'width' => 24, 'height' => 4 ], [ 'type' => 'trigover', 'name' => self::$delete_widget, 'x' => 0, 'y' => 4, 'width' => 24, 'height' => 4, 'fields' => [ [ 'type' => 0, 'name' => 'show_suppressed', 'value' => 1 ] ] ] ] ], [ 'name' => self::$create_page, 'widgets' => [] ] ] ] ]); self::$dashboardid = $response['dashboardids'][0]; $timestamp = time(); // Resolve one of existing problems to create a recent problem. CDBHelper::setTriggerProblem(self::$resolved_trigger, TRIGGER_VALUE_FALSE, ['clock' => $timestamp]); $triggerid = CDBHelper::getValue('SELECT triggerid FROM triggers WHERE description='.zbx_dbstr(self::$dependency_trigger)); // Change the resolved triggers blinking period as the default value is too small for this test. CDataHelper::call('settings.update', ['blink_period' => '10m']); // Enable the trigger that other triggers depend on. CDataHelper::call('trigger.update', [['triggerid' => $triggerid, 'status' => TRIGGER_STATUS_ENABLED]]); } public function testDashboardTriggerOverviewWidget_Layout() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid); $form = CDashboardElement::find()->one()->edit()->addWidget()->asForm(); $form->fill(['Type' => CFormElement::RELOADABLE_FILL('Trigger overview')]); $this->assertEquals(['Type', 'Name', 'Refresh interval', 'Show', 'Host groups', 'Hosts', 'Tags', '', 'Show suppressed problems', 'Hosts location'], $form->getLabels()->asText() ); $default_values = [ 'Show header' => true, 'Name' => '', 'Refresh interval' => 'Default (1 minute)', 'Show' => 'Recent problems', 'Host groups' => '', 'Hosts' => '', 'id:evaltype' => 'And/Or', 'id:tags_0_tag' => '', 'id:tags_0_value' => '', 'id:tags_0_operator' => 'Contains', 'Show suppressed problems' => false, 'Hosts location' => 'Left' ]; $form->checkValue($default_values); // Check field lengths and placeholders. foreach (['Name' => 'default', 'id:tags_0_tag' => 'tag', 'id:tags_0_value' => 'value'] as $field => $placeholder) { $field = $form->getField($field); $this->assertEquals(255, $field->getAttribute('maxlength')); $this->assertEquals($placeholder, $field->getAttribute('placeholder')); } // Check operators dropdown options. $this->assertEquals(['Exists', 'Equals', 'Contains', 'Does not exist', 'Does not equal', 'Does not contain'], $form->getField('id:tags_0_operator')->asDropdown()->getOptions()->asText() ); // Check possible values of radio buttons. $radio_buttons = [ 'Show' => ['Recent problems', 'Problems', 'Any'], 'Tags' => ['And/Or', 'Or'], 'Hosts location' => ['Left', 'Top'] ]; foreach ($radio_buttons as $radio_button => $values) { $radio_element = $form->getField($radio_button); $this->assertEquals($values, $radio_element->getLabels()->asText()); } // Check buttons in Tags table. $this->assertEquals(2, $form->query('id:tags_table_tags')->one()->query('button', ['Add', 'Remove'])->all() ->filter(new CElementFilter(CElementFilter::CLICKABLE))->count() ); // Close the widget configuration form dialog to avoid possible alerts in following tests. COverlayDialogElement::find()->one()->close(); } public function getWidgetData() { return [ // Create a widget with default values including default name. [ [ 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Average', '1_trigger_Disaster', '1_trigger_High', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ], 'Host for triggers filtering' => [ 'Inheritance trigger with tags' ] ] ] ], // Create a widget that displays only problems. [ [ 'fields' => [ 'Name' => 'Show problems', 'Show' => 'Problems' ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Disaster', '1_trigger_High', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ], 'Host for triggers filtering' => [ 'Inheritance trigger with tags' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Show all triggers for specific host', 'Show' => 'Any', 'Hosts' => ['3_Host_to_check_Monitoring_Overview'] ], 'expected' => [ '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average', '3_trigger_Disaster' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Show problems for specific hostgroup', 'Show' => 'Problems', 'Host groups' => ['Group to check Overview'] ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Disaster', '1_trigger_High', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Show problems for multiple hostgroups', 'Show' => 'Problems', 'Host groups' => ['Group to check Overview', 'Another group to check Overview'] ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Disaster', '1_trigger_High', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Show recent problems for multiple hosts', 'Show' => 'Any', 'Hosts' => ['3_Host_to_check_Monitoring_Overview', '4_Host_to_check_Monitoring_Overview'] ], 'expected' => [ '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average', '3_trigger_Disaster' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Hostgroup without triggers', 'Host groups' => ['Dynamic widgets HG1 (H1 and H2)'] ] ] ], [ [ 'fields' => [ 'Name' => 'Host without triggers', 'Hosts' => ['Dynamic widgets H1'] ] ] ], [ [ 'fields' => [ 'Name' => 'Combination of non-related Host and Hostgroup', 'Host groups' => ['Group to check Overview'], 'Hosts' => ['4_Host_to_check_Monitoring_Overview'] ] ] ], [ [ 'fields' => [ 'Name' => 'Show suppressed problems + hosts on top', 'Show suppressed problems' => true, 'Hosts location' => 'Top' ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Average', '1_trigger_Disaster', '1_trigger_High', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ], 'Host for suppression' => [ 'Trigger_for_suppression' ], 'Host for triggers filtering' => [ 'Inheritance trigger with tags' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Filter triggers by tag with default operator' ], 'tags' => [ ['name' => 'server', 'operator' => 'Contains', 'value' => 'sel'] ], 'expected' => [ 'Host for triggers filtering' => [ 'Inheritance trigger with tags' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Filter triggers by 2 tags with Or operator', 'Tags' => 'Or' ], 'tags' => [ ['name' => 'Street', 'operator' => 'Exists'], ['name' => 'webhook', 'operator' => 'Equals', 'value' => '1'] ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_High' ], 'Host for triggers filtering' => [ 'Inheritance trigger with tags' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Does not exists and Does not equal tag operators', 'Show' => 'Problems' ], 'tags' => [ ['name' => 'Street', 'operator' => 'Does not exist'], ['name' => 'webhook', 'operator' => 'Does not equal', 'value' => '1'] ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Disaster', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Виджет с tag + 良い1日を un žšī!@#$%^&*()_ vardā' ], 'tags' => [ ['name' => 'Street', 'operator' => 'Does not contain', 'value' => 'elza'] ], 'expected' => [ '1_Host_to_check_Monitoring_Overview' => [ '1_trigger_Average', '1_trigger_Disaster', '1_trigger_High', '1_trigger_Not_classified', '1_trigger_Warning', '2_trigger_Information' ], '3_Host_to_check_Monitoring_Overview' => [ '3_trigger_Average' ], '4_Host_to_check_Monitoring_Overview' => [ '4_trigger_Average' ] ] ] ], [ [ 'fields' => [ 'Name' => 'No result - filter triggers by 2 tags with And operator' ], 'tags' => [ ['name' => 'server', 'operator' => 'Contains', 'value' => 'sel'], ['name' => 'webhook', 'operator' => 'Equals', 'value' => '1'] ] ] ], [ [ 'fields' => [ 'Name' => 'Filter by 2 tags without value', 'Tags' => 'Or' ], 'tags' => [ ['name' => 'server', 'operator' => 'Contains', 'value' => ''], ['name' => 'webhook', 'operator' => 'Equals', 'value' => ''] ], 'expected' => [ 'Host for triggers filtering' => [ 'Inheritance trigger with tags' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Only tag specified only by value' ], 'tags' => [ ['name' => '', 'operator' => 'Contains', 'value' => '1'] ] ] ], [ [ 'fields' => [ 'Name' => 'Check triggers with dependency icons', 'Show' => 'Any', 'Hosts' => [self::$icon_host] ], 'expected' => [ 'Host for triggers filtering' => [ 'Dependent trigger ONE', 'Discovered trigger one', 'Inheritance trigger with tags', 'Trigger disabled with tags' ] ] ] ] ]; } /** * @dataProvider getWidgetData */ public function testDashboardTriggerOverviewWidget_Create($data) { $this->checkWidgetAction($data); } /** * @dataProvider getWidgetData */ public function testDashboardTriggerOverviewWidget_Update($data) { $this->checkWidgetAction($data, false); } public function testDashboardTriggerOverviewWidget_SimpleUpdate() { $old_hash = CDBHelper::getHash($this->sql); $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid); $dashboard = CDashboardElement::find()->one(); $dashboard->edit(); $form = $dashboard->getWidget(self::$update_widget)->edit(); $form->submit(); COverlayDialogElement::ensureNotPresent(); $widget = $dashboard->getWidget(self::$update_widget); $widget->waitUntilReady(); $dashboard->save(); $this->assertMessage(TEST_GOOD, 'Dashboard updated'); $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); } public function getCancelActionsData() { return [ // Cancel update widget. [ [ 'update' => true, 'save_widget' => true, 'save_dashboard' => false ] ], [ [ 'update' => true, 'save_widget' => false, 'save_dashboard' => true ] ], // Cancel create widget. [ [ 'save_widget' => true, 'save_dashboard' => false ] ], [ [ 'save_widget' => false, 'save_dashboard' => true ] ] ]; } /** * @dataProvider getCancelActionsData */ public function testDashboardTriggerOverviewWidget_Cancel($data) { $old_hash = CDBHelper::getHash($this->sql); $new_name = 'Widget to be cancelled'; $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid); $dashboard = CDashboardElement::find()->one()->edit(); // Start updating or creating a widget. if (CTestArrayHelper::get($data, 'update', false)) { $form = $dashboard->getWidget(self::$update_widget)->edit(); } else { $form = $dashboard->addWidget()->asForm(); if ($form->getField('Type')->getValue() !== 'Trigger overview') { $form->getField('Type')->fill('Trigger overview'); $form->invalidate(); } } $form->fill([ 'Name' => $new_name, 'Refresh interval' => '10 minutes', 'Show' => 'Any', 'Host groups' => ['Another group to check Overview'], 'Hosts' => ['4_Host_to_check_Monitoring_Overview'], 'Tags' => 'Or', 'Show suppressed problems' => 'true', 'Hosts location' => 'Top' ]); $this->setTags([['name' => 'webhook', 'operator' => 'Equals', 'value' => '1']]); // Save or cancel widget. if (CTestArrayHelper::get($data, 'save_widget', false)) { $form->submit(); // Check that changes took place on the unsaved dashboard (widget got renamed). $this->assertTrue($dashboard->getWidget($new_name)->isValid()); } else { $dialog = COverlayDialogElement::find()->one(); $dialog->query('button:Cancel')->one()->click(); $dialog->ensureNotPresent(); if (CTestArrayHelper::get($data, 'update', false)) { foreach ([self::$update_widget => true, $new_name => false] as $name => $valid) { $this->assertTrue($dashboard->getWidget($name, $valid)->isValid($valid)); } } } // Save or cancel dashboard update. if (CTestArrayHelper::get($data, 'save_dashboard', false)) { $dashboard->save(); } else { $dashboard->cancelEditing(); } // Confirm that no changes were made to the widget. $this->assertEquals($old_hash, CDBHelper::getHash($this->sql)); } public function testDashboardTriggerOverviewWidget_Delete() { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid); $dashboard = CDashboardElement::find()->one()->edit(); $widget = $dashboard->getWidget(self::$delete_widget); $dashboard->deleteWidget(self::$delete_widget); $widget->waitUntilNotPresent(); $dashboard->save(); $this->assertMessage(TEST_GOOD, 'Dashboard updated'); // Confirm that widget is not present on dashboard. $this->assertFalse($dashboard->getWidget(self::$delete_widget, false)->isValid()); $widget_sql = 'SELECT null FROM widget_field wf'. ' LEFT JOIN widget w'. ' ON w.widgetid=wf.widgetid'. ' WHERE w.name='.zbx_dbstr(self::$delete_widget); $this->assertEquals(0, CDBHelper::getCount($widget_sql)); } /** * Function checks the content of the Dependent and Depends on popups. * Icons with Acknowledge popup menus are not checked as they are covered in testPageTriggerUrl test. */ public function testDashboardTriggerOverviewWidget_CheckDependencyPopups() { $popup_content = [ 'Dependent trigger ONE' => [ 'Depends on' => ['Trigger disabled with tags'] ], 'Inheritance trigger with tags' => [ 'Depends on' => ['Trigger disabled with tags'] ], 'Trigger disabled with tags' => [ 'Dependent' => ['Inheritance trigger with tags', 'Dependent trigger ONE'] ] ]; $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid); $dashboard = CDashboardElement::find()->one()->edit(); $form = $dashboard->getWidget(self::$update_widget)->edit(); $form->fill(['Show' => 'Any', 'Hosts' => [self::$icon_host]]); $form->submit(); // Wait for the widget to be ready and save dashboard (the wait is performed within the getWidget() method). $dashboard->getWidget(self::$update_widget); $dashboard->save(); // Get the table row with all triggers (since all of them belong to a single host). $row = $dashboard->getWidget(self::$update_widget)->getContent()->asTable()->findRow('Hosts', self::$icon_host); foreach ($popup_content as $trigger => $dependency) { // Locate hint and check table headers in hint. $hint_table = $row->getColumn($trigger)->query('class:hint-box')->one()->asTable(); $this->assertEquals(array_keys($dependency), $hint_table->getHeadersText()); // Gather data from rows and compare result with reference. $hint_rows = $hint_table->getRows()->asText(); $this->assertEquals(array_values($dependency), [$hint_rows]); } } /** * Create or update a Trigger overview widget and check the result. * * @param array $data widget related data from data provider * @param boolean $create flag that specifies whether a create action is performed */ public function checkWidgetAction($data, $create = true) { $this->page->login()->open('zabbix.php?action=dashboard.view&dashboardid='.self::$dashboardid); $dashboard = CDashboardElement::find()->one(); $dashboard->edit(); if ($create) { $dashboard->selectPage(self::$create_page); $form = $dashboard->addWidget()->asForm(); // Set type to Trigger overview in case if this field has a different value. if ($form->getField('Type')->getValue() !== 'Trigger overview') { $form->fill(['Type' => CFormElement::RELOADABLE_FILL('Trigger overview')]); } } else { $form = $dashboard->getWidget(self::$update_widget)->edit(); // Values from the previous cases should be cleaned-up in case of update scenario before filling-in data. $this->cleanupFormBeforeFill($form, CTestArrayHelper::get($data, 'fields', [])); } // Fill form in case if values that are different from widget default configuration should be filled. if (array_key_exists('fields', $data)) { $form->fill($data['fields']); } if (CTestArrayHelper::get($data,'tags', false)) { $this->setTags($data['tags']); } $form->submit(); COverlayDialogElement::ensureNotPresent(); $widget_name = (array_key_exists('fields', $data)) ? $data['fields']['Name'] : 'Trigger overview'; $widget = $dashboard->getWidget($widget_name); $dashboard->save(); $this->assertMessage(TEST_GOOD, 'Dashboard updated'); if ($create) { $dashboard->selectPage(self::$create_page); } else { self::$update_widget = (array_key_exists('fields', $data)) ? $data['fields']['Name'] : 'Trigger overview'; } $table = $widget->getContent()->asTable(); if (CTestArrayHelper::get($data, 'fields.Hosts location') === 'Top') { $expected_headers = ['Triggers']; $expected_rows = []; } else { $expected_headers = ['Hosts']; $expected_rows = array_keys(CTestArrayHelper::get($data, 'expected', [])); } // Check empty result widget and proceed to next case. if (!array_key_exists('expected', $data)) { $this->assertEquals($expected_headers, $table->getHeadersText()); $this->assertTableData(null, "xpath://h4[text()=".CXPathHelper::escapeQuotes($data['fields']['Name']). "]/../..//table" ); return; } // Check widget content based on the alignment chosen in Hosts location field. foreach ($data['expected'] as $host => $triggers) { if (CTestArrayHelper::get($data, 'fields.Hosts location') === 'Top') { $expected_headers[] = $host; foreach ($triggers as $trigger) { $expected_rows[] = $trigger; $cell = $table->findRow('Triggers', $trigger)->getColumn($host); $this->checkTriggerCell($cell, $trigger); } } else { $row = $table->findRow('Hosts', $host); foreach ($triggers as $trigger) { $expected_headers[] = $trigger; $cell = $row->getColumn($trigger); $this->checkTriggerCell($cell, $trigger); } } } // Rows are sorted alphabetically in widget, so the same should apply to the reference array. $expected_rows = array_values($expected_rows); sort($expected_rows); $this->assertEquals($expected_headers, $table->getHeadersText()); $this->assertTableDataColumn($expected_rows, $expected_headers[0], 'xpath://h4[text()='. CXPathHelper::escapeQuotes($widget_name).']/../..//table[@class="list-table"]' ); } /** * Remove the previously entered values from widget configuration form. * * @param CFormElement $form widget configuration form element */ private function cleanupFormBeforeFill($form) { $default_values = [ 'Name' => '', 'Show' => 'Recent problems', 'Host groups' => '', 'Hosts' => '', 'Tags' => 'And/Or', 'Show suppressed problems' => false, 'Hosts location' => 'Left' ]; foreach ($default_values as $field_name => $value) { $field = $form->getField($field_name); if ($field->getValue() !== $value) { if (in_array($field, ['Host groups', 'Hosts'])) { $field->clear(); } else { $field->fill($value); } } } // Remove tags left from previous case and add a blank row for new data. if ($form->getField('id:tags_0_tag')->getValue() !== '' || $form->getField('id:tags_0_value')->getValue() !== '') { $form->query('button:Remove')->all()->click(); $form->query('button:Add')->one()->click(); } } /** * Check the severity and the icon displayed in the table cell under attention. * * @param CElement $cell table cell that represents the trigger to be checked * @param string $trigger the name of the trigger that is represented by the trigger cell */ private function checkTriggerCell ($cell, $trigger) { // Check the colour of the background. $this->assertStringStartsWith(self::$background_classes[$trigger], $cell->getAttribute('class')); // Check trigger icon if such should exist. if (in_array($trigger, self::$trigger_icons)) { $element = (self::$trigger_icons[$trigger] === 'icon-ackn') ? 'span' : 'a'; $icon = $cell->query('xpath:.//'.$element)->one(); $this->assertTrue($icon->isValid()); $this->assertStringStartsWith(self::$trigger_icons[$trigger], $cell->getAttribute('class')); } } }