|
|
|
|
<?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';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataSource WebScenarios
|
|
|
|
|
*
|
|
|
|
|
* @onBefore getContextData
|
|
|
|
|
*
|
|
|
|
|
* @backup httptest
|
|
|
|
|
*/
|
|
|
|
|
class testFormWebScenarioStep extends CWebTest {
|
|
|
|
|
|
|
|
|
|
protected static $templateid;
|
|
|
|
|
protected static $update_step = 'step 2 of clone scenario';
|
|
|
|
|
|
|
|
|
|
const IMPACTLESS_STEP = 'Первый этап вэб сценария';
|
|
|
|
|
const HOSTID = 40001;
|
|
|
|
|
const TEMPLATE_SCENARIO = 'Template_Web_scenario';
|
|
|
|
|
const UPDATE_SCENARIO = 'Scenario for Clone';
|
|
|
|
|
const CREATE_SCENARIO = 'Scenario for Update';
|
|
|
|
|
const SQL = 'SELECT * FROM httpstep hs INNER JOIN httpstep_field hsf ON hsf.httpstepid = hs.httpstepid';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Attach MessageBehavior to the test.
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public function getBehaviors() {
|
|
|
|
|
return [CMessageBehavior::class];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the necessary properties of entities used within this test.
|
|
|
|
|
*/
|
|
|
|
|
public static function getContextData() {
|
|
|
|
|
self::$templateid = CDataHelper::get('WebScenarios.templateid');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function getStepLayoutData() {
|
|
|
|
|
return [
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'context' => 'host'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'scenario_name' => self::TEMPLATE_SCENARIO,
|
|
|
|
|
'step_name' => 'step 1 of scenario 1',
|
|
|
|
|
'context' => 'host'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'scenario_name' => self::TEMPLATE_SCENARIO,
|
|
|
|
|
'context' => 'template'
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider getStepLayoutData
|
|
|
|
|
*/
|
|
|
|
|
public function testFormWebScenarioStep_CheckLayout($data) {
|
|
|
|
|
$context_id = ($data['context'] === 'host') ? self::HOSTID : self::$templateid;
|
|
|
|
|
$this->page->login()->open('httpconf.php?filter_set=1&filter_hostids%5B0%5D='.$context_id.'&context='.$data['context'])
|
|
|
|
|
->waitUntilReady();
|
|
|
|
|
|
|
|
|
|
// Open the step configuration form for the corresponding web scenario.
|
|
|
|
|
$selector = (array_key_exists('scenario_name', $data)) ? $data['scenario_name'] : self::UPDATE_SCENARIO;
|
|
|
|
|
|
|
|
|
|
$this->query('link', $selector)->waitUntilClickable()->one()->click();
|
|
|
|
|
$scenario_form = $this->query('name:webscenario_form')->waitUntilVisible()->asForm()->one();
|
|
|
|
|
|
|
|
|
|
$scenario_form->selectTab('Steps');
|
|
|
|
|
$steps_table = $scenario_form->getField('Steps')->asTable();
|
|
|
|
|
|
|
|
|
|
// Steps cannot be added to templated web scenario from host, so in this case the existing step is opened.
|
|
|
|
|
if (array_key_exists('step_name', $data)) {
|
|
|
|
|
$steps_table->findRow('Name', $data['step_name'])->getColumn('Name')->click();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$steps_table->query('button:Add')->waitUntilClickable()->one()->click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$dialog = COverlayDialogElement::find()->waitUntilReady()->one();
|
|
|
|
|
$step_form = $dialog->asForm();
|
|
|
|
|
|
|
|
|
|
$title = (array_key_exists('step_name', $data)) ? 'Step of web scenario' : 'New step of web scenario';
|
|
|
|
|
$this->assertEquals($title, $dialog->getTitle());
|
|
|
|
|
|
|
|
|
|
// TODO: xpath quotes should be fixed after git-hook improvements in DEV-2396.
|
|
|
|
|
$step_fields = [
|
|
|
|
|
'Name' => ['maxlength' => 64],
|
|
|
|
|
'id:url' => [],
|
|
|
|
|
"xpath:(.//table[@id='step-query-fields']//textarea)[1]" => ['placeholder' => 'name', 'maxlength' => 255],
|
|
|
|
|
"xpath:(.//table[@id='step-query-fields']//textarea)[2]" => ['placeholder' => 'value', 'maxlength' => 255],
|
|
|
|
|
"xpath:(.//table[@id='step-post-fields']//textarea)[1]" => ['placeholder' => 'name', 'maxlength' => 255],
|
|
|
|
|
"xpath:(.//table[@id='step-post-fields']//textarea)[2]" => ['placeholder' => 'value', 'maxlength' => 2000],
|
|
|
|
|
'Post type' => ['value' => 'Form data'],
|
|
|
|
|
'Raw post' => ['visible' => false],
|
|
|
|
|
"xpath:(.//table[@id='step-variables']//textarea)[1]" => ['placeholder' => 'name', 'maxlength' => 255],
|
|
|
|
|
"xpath:(.//table[@id='step-variables']//textarea)[2]" => ['placeholder' => 'value', 'maxlength' => 2000],
|
|
|
|
|
"xpath:(.//table[@id='step-headers']//textarea)[1]" => ['placeholder' => 'name', 'maxlength' => 255],
|
|
|
|
|
"xpath:(.//table[@id='step-headers']//textarea)[2]" => ['placeholder' => 'value', 'maxlength' => 2000],
|
|
|
|
|
'Follow redirects' => ['value' => false],
|
|
|
|
|
'Retrieve mode' => ['value' => 'Body'],
|
|
|
|
|
'Timeout' => ['value' => '15s', 'maxlength' => 255],
|
|
|
|
|
'Required string' => ['placeholder' => 'pattern', 'maxlength' => 255],
|
|
|
|
|
'Required status codes' => ['maxlength' => 255]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Differences between step creation form and update form of templated scenario step should be taken into account.
|
|
|
|
|
if (array_key_exists('step_name', $data)) {
|
|
|
|
|
$step_fields['Name'] = ['value' => $data['step_name'], 'enabled' => false, 'maxlength' => 64];
|
|
|
|
|
$step_fields['id:url']['value'] = 'http://zabbix.com';
|
|
|
|
|
$step_fields['Post type']['value'] = 'Raw data';
|
|
|
|
|
$step_fields['Raw post']['visible'] = true;
|
|
|
|
|
$step_fields['Follow redirects']['value'] = true;
|
|
|
|
|
|
|
|
|
|
$initial_type = 'Raw data';
|
|
|
|
|
$new_type = 'Form data';
|
|
|
|
|
$buttons = ['Parse', 'Update', 'Cancel'];
|
|
|
|
|
$post_fields = ['Post type', 'Raw post'];
|
|
|
|
|
|
|
|
|
|
// TODO: xpath quotes should be fixed after git-hook improvements in DEV-2396.
|
|
|
|
|
foreach (['[1]', '[2]'] as $element_index) {
|
|
|
|
|
$xpath = "xpath:(.//table[@id='step-post-fields']//textarea)".$element_index;
|
|
|
|
|
|
|
|
|
|
unset($step_fields[$xpath]);
|
|
|
|
|
$this->assertFalse($step_form->query($xpath)->one(false)->isValid());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$initial_type = 'Form data';
|
|
|
|
|
$new_type = 'Raw data';
|
|
|
|
|
$buttons = ['Parse', 'Add', 'Cancel'];
|
|
|
|
|
$post_fields = ['Post type', 'Post fields'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($step_fields as $field => $attributes) {
|
|
|
|
|
$value = (array_key_exists('value', $attributes)) ? $attributes['value'] : '';
|
|
|
|
|
$visible = (array_key_exists('visible', $attributes)) ? $attributes['visible'] : true;
|
|
|
|
|
$enabled = (array_key_exists('enabled', $attributes)) ? $attributes['enabled'] : true;
|
|
|
|
|
|
|
|
|
|
$this->assertEquals($visible, $step_form->getField($field)->isVisible(), $field.' visibility is not '.$visible);
|
|
|
|
|
$this->assertEquals($value, $step_form->getField($field)->getValue());
|
|
|
|
|
$this->assertTrue($step_form->getField($field)->isEnabled($enabled));
|
|
|
|
|
|
|
|
|
|
foreach (['maxlength', 'placeholder'] as $attribute) {
|
|
|
|
|
if (array_key_exists($attribute, $attributes)) {
|
|
|
|
|
$this->assertEquals($attributes[$attribute], $step_form->getField($field)->getAttribute($attribute));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check mandatory fields.
|
|
|
|
|
$this->assertEquals(['Name', 'URL', 'Timeout'], array_values($step_form->getRequiredLabels()));
|
|
|
|
|
|
|
|
|
|
// Check Labels in radio buttons.
|
|
|
|
|
$radio_buttons = [
|
|
|
|
|
'Post type' => ['Form data', 'Raw data'],
|
|
|
|
|
'Retrieve mode' => ['Body', 'Headers', 'Body and headers']
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
foreach ($radio_buttons as $radio_button => $labels) {
|
|
|
|
|
$this->assertEquals($labels, $step_form->getField($radio_button)->getLabels()->asText());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check that changing the value in Post type field results in displaying either Post fields or Raw post field.
|
|
|
|
|
$field_visibility = [
|
|
|
|
|
'Form data' => ['Post fields' => true, 'Raw post' => false],
|
|
|
|
|
'Raw data' => ['Post fields' => false, 'Raw post' => true]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Check visibility of the post related fields based on the initially selected post type.
|
|
|
|
|
foreach ([$new_type, $initial_type] as $post_type) {
|
|
|
|
|
$step_form->getField('Post type')->select($post_type);
|
|
|
|
|
|
|
|
|
|
foreach ($field_visibility[$post_type] as $post_field => $visible) {
|
|
|
|
|
$this->assertEquals($visible, $step_form->getField($post_field)->isDisplayed());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$mode_field = $step_form->getField('Retrieve mode');
|
|
|
|
|
|
|
|
|
|
// Check that "Post fields" related fields are disabled only when Retrieve mode is set to Headers.
|
|
|
|
|
foreach (['Body and headers' => true, 'Headers' => false, 'Body' => true] as $value => $enabled) {
|
|
|
|
|
$mode_field->select($value);
|
|
|
|
|
|
|
|
|
|
foreach ($post_fields as $post_field) {
|
|
|
|
|
/*
|
|
|
|
|
* Post fields table has the disabled class even when enabled to disable the drag icon if table has only
|
|
|
|
|
* one row. Therefore, the state of all four interactable elements is checked induvidually.
|
|
|
|
|
*/
|
|
|
|
|
if ($post_field === 'Post fields') {
|
|
|
|
|
$post_fields_table = $step_form->getField($post_field);
|
|
|
|
|
|
|
|
|
|
foreach (['xpath:(.//textarea)[1]', 'xpath:(.//textarea)[2]', 'button:Add', 'button:Remove'] as $element) {
|
|
|
|
|
$this->assertTrue($post_fields_table->query($element)->one()->isEnabled($enabled));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$this->assertTrue($step_form->getField($post_field)->isEnabled($enabled));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set Post type to Form data in case of templated web scenario, so that Post field table would be displayed.
|
|
|
|
|
if (array_key_exists('step_name', $data)) {
|
|
|
|
|
$step_form->getField('Post type')->select('Form data');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check the layout of table fields.
|
|
|
|
|
$table_layout = [
|
|
|
|
|
'headers' => ['', 'Name', '', 'Value', '']
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Check the layout of the value pair field tables.
|
|
|
|
|
foreach (['Query fields', 'Post fields', 'Variables', 'Headers'] as $table_name) {
|
|
|
|
|
$table = $step_form->getField($table_name)->asTable();
|
|
|
|
|
$row = $table->getRow(0);
|
|
|
|
|
$this->assertSame($table_layout['headers'], $table->getHeadersText());
|
|
|
|
|
|
|
|
|
|
// Check that Add button is clickable and the Remove button is not.
|
|
|
|
|
$add_button = $table->query('button:Add')->one();
|
|
|
|
|
$this->assertTrue($add_button->isClickable());
|
|
|
|
|
$remove_button = $row->query('button:Remove')->one();
|
|
|
|
|
$this->assertTrue($remove_button->isClickable());
|
|
|
|
|
$remove_button->click();
|
|
|
|
|
$this->assertFalse($remove_button->isClickable());
|
|
|
|
|
|
|
|
|
|
// Check the presence of the draggable icon.
|
|
|
|
|
if ($table_name === 'Variables') {
|
|
|
|
|
$this->assertFalse($row->query('class:drag-icon')->one(false)->isValid());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$drag_icon = $row->query('class:drag-icon')->one();
|
|
|
|
|
$this->assertFalse($drag_icon->isEnabled());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fill in some data in first row and check that Remove buttons and draggable icon became enabled.
|
|
|
|
|
foreach(['Name', 'Value'] as $column) {
|
|
|
|
|
$row->getColumn($column)->query('xpath:./textarea')->one()->fill('zabbix');
|
|
|
|
|
}
|
|
|
|
|
$this->assertTrue($row->query('button:Remove')->one()->isClickable());
|
|
|
|
|
|
|
|
|
|
// Check that draggable icon becomes enabled when a new row is added.
|
|
|
|
|
if ($table_name !== 'Variables') {
|
|
|
|
|
$this->assertFalse($drag_icon->isEnabled());
|
|
|
|
|
$add_button->click();
|
|
|
|
|
$this->assertTrue($drag_icon->isEnabled());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check the buttons in the web scenario step coniguration form.
|
|
|
|
|
foreach ($buttons as $button) {
|
|
|
|
|
$this->assertTrue($dialog->query('button', $button)->one()->isClickable());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function getWebScenarioStepData() {
|
|
|
|
|
return [
|
|
|
|
|
// #0 Empty name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => '',
|
|
|
|
|
'id:url' => 'https://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "name": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #1 Empty space in name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => ' ',
|
|
|
|
|
'id:url' => 'https://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "name": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #2 Empty URL.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with empty URL',
|
|
|
|
|
'id:url' => ''
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "url": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #3 Blank space in URL.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with blank space in URL',
|
|
|
|
|
'id:url' => ' '
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "url": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #4 Empty Query field name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with missing query field name',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'query fields' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '',
|
|
|
|
|
'value' => 'query field value'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "query_fields/1/name": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #5 Empty Post field name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with missing post field name',
|
|
|
|
|
'Post type' => 'Form data',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'post fields' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '',
|
|
|
|
|
'value' => 'post field value'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "post_fields/1/name": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #6 Empty Variables field name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with missing variable name',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '',
|
|
|
|
|
'value' => 'variable field value'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/1/name": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #7 Variables field name without opening bracket.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with missing variable nameopening bracket',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => 'name}'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/1/name": is not enclosed in {} or is malformed.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #8 Variables field name without closing bracket.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Step with missing variable name closing bracket',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{name'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/1/name": is not enclosed in {} or is malformed.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #9 Misplaced brackets in Variables field name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Misplaced brackets in Variables field name',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{na}me'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/1/name": is not enclosed in {} or is malformed.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #10 Double brackets in Variables field name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Double brackets in Variables field name',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{{name}}'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/1/name": is not enclosed in {} or is malformed.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #11 Only brackets in Variables field name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Only brackets in Variables field name',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{}'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/1/name": is not enclosed in {} or is malformed.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #12 Duplicate Variable names.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Duplicate Variable names',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{name}',
|
|
|
|
|
'value' => 'AAA'
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => '{name}',
|
|
|
|
|
'value' => 'BBB'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "variables/2": value (name)=({name}) already exists.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #13 Missing Headers name.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Missing Headers name',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
],
|
|
|
|
|
'headers' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '',
|
|
|
|
|
'value' => 'AAA'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "headers/1/name": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #14 Empty timeout.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Empty timeout',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => ''
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #15 Empty space in timeout.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Empty space in timeout',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => ' '
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": cannot be empty.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #16 Non-numeric timeout.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Non-numeric timeout',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => 'two'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": a time unit is expected.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #17 Negative timeout.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Negative timeout',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => '-5s'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": a time unit is expected.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #18 Zero timeout.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Zero timeout',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => 0
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": value must be one of 1-3600.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #19 Too big timeout.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Too big timeout',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => 3601
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": value must be one of 1-3600.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #20 Too big timeout with suffix.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Too big timeout with suffix',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Timeout' => '2h'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Incorrect value for field "timeout": value must be one of 1-3600.'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #21 Non-numeric status code.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Non-numeric status code',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Required status codes' => 'AAA'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Invalid response code "AAA".'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #22 Too big status code.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Too big status code',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Required status codes' => '2150000000'
|
|
|
|
|
],
|
|
|
|
|
'error' => 'Invalid response code "2150000000".'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #23 Minimal step configuration.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Min config step',
|
|
|
|
|
'id:url' => 'http://zabbix.com'
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #24 Retrieve mode set to Headers - Disabled post fields.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'Retrieve headers',
|
|
|
|
|
'id:url' => 'http://zabbix.com',
|
|
|
|
|
'Retrieve mode' => 'Headers'
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #25 All fields populated.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => 'All possible fields specified',
|
|
|
|
|
'id:url' => '良い一日を',
|
|
|
|
|
'Retrieve mode' => 'Body and headers',
|
|
|
|
|
'Post type' => 'Raw data',
|
|
|
|
|
'Raw post' => 'name=良い一日を',
|
|
|
|
|
'Follow redirects' => true,
|
|
|
|
|
'Timeout' => '33s',
|
|
|
|
|
'Required string' => '良い一日を',
|
|
|
|
|
'Required status codes' => '200,300,401'
|
|
|
|
|
],
|
|
|
|
|
'query fields' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '1st query name- 良い一日を',
|
|
|
|
|
'value' => ''
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => '2nd query name - 良い一日を',
|
|
|
|
|
'value' => '2nd query value - 良い一日を'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{1st variable name - 良い一日を}',
|
|
|
|
|
'value' => ''
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => '{the 2nd variable name - 良い一日を}',
|
|
|
|
|
'value' => '2nd variable value - 良い一日を'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'headers' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '1st header name - 良い一日を',
|
|
|
|
|
'value' => '1st header value - 良い一日を'
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => '2nd header name - 良い一日を',
|
|
|
|
|
'value' => ''
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #26 Maximal allowed length of fields except for timeout since maxlength is 255 but maxvalue is 3600.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => STRING_64,
|
|
|
|
|
'id:url' => 'URL has no maxlength',
|
|
|
|
|
'Post type' => 'Form data',
|
|
|
|
|
'Timeout' => '3600s',
|
|
|
|
|
'Required string' => STRING_255,
|
|
|
|
|
'Required status codes' => '200'.str_repeat(',200', 63)
|
|
|
|
|
],
|
|
|
|
|
'query fields' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => STRING_255,
|
|
|
|
|
'value' => STRING_255
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => 'query_name',
|
|
|
|
|
'value' => 'query_value'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'post fields' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => STRING_255,
|
|
|
|
|
'value' => STRING_2000
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => 'post_field_name',
|
|
|
|
|
'value' => 'post_field_value'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'variables' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => '{'.substr(STRING_255, 0, 253).'}',
|
|
|
|
|
'value' => STRING_2000
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => '{variable_name}',
|
|
|
|
|
'value' => 'variable_value'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
'headers' => [
|
|
|
|
|
[
|
|
|
|
|
'name' => STRING_255,
|
|
|
|
|
'value' => STRING_2000
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'name' => 'header_name',
|
|
|
|
|
'value' => 'header_value'
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #27 Trim trailing and leading spaces from step fields.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'fields' => [
|
|
|
|
|
'Name' => ' Step with trailing and leading spaces ',
|
|
|
|
|
'id:url' => ' http://zabbix.com' ,
|
|
|
|
|
'Timeout' => ' 15 ',
|
|
|
|
|
'Required string' => ' Zabbix ',
|
|
|
|
|
'Required status codes' => ' 404 '
|
|
|
|
|
],
|
|
|
|
|
'trim' => true
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider getWebScenarioStepData
|
|
|
|
|
*/
|
|
|
|
|
public function testFormWebScenarioStep_Create($data) {
|
|
|
|
|
$this->checkStepAction($data, 'create');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider getWebScenarioStepData
|
|
|
|
|
*/
|
|
|
|
|
public function testFormWebScenarioStep_Update($data) {
|
|
|
|
|
$this->checkStepAction($data, 'update');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Perform create or update action for a web scenario step and check the result.
|
|
|
|
|
*
|
|
|
|
|
* @param array $data data provider
|
|
|
|
|
* @param string $action action to be performed
|
|
|
|
|
*/
|
|
|
|
|
protected function checkStepAction($data, $action) {
|
|
|
|
|
$expected = CTestArrayHelper::get($data, 'expected', TEST_GOOD);
|
|
|
|
|
|
|
|
|
|
// Open the web scenario step configuration form in create or update mode depending on the executed action.
|
|
|
|
|
$scenario = ($action === 'update') ? self::UPDATE_SCENARIO : self::CREATE_SCENARIO;
|
|
|
|
|
$scenario_form = $this->getScenarioFormOnStepsTab($scenario);
|
|
|
|
|
$steps_table = $scenario_form->getField('Steps')->asTable();
|
|
|
|
|
|
|
|
|
|
$open_step = ($action === 'create') ? 'button:Add' : 'link:'.self::$update_step;
|
|
|
|
|
$steps_table->query($open_step)->waitUntilClickable()->one()->click();
|
|
|
|
|
|
|
|
|
|
$dialog = COverlayDialogElement::find()->waitUntilReady()->one();
|
|
|
|
|
$step_form = $dialog->asForm();
|
|
|
|
|
|
|
|
|
|
$step_form->fill($data['fields']);
|
|
|
|
|
|
|
|
|
|
foreach (['variables', 'query fields', 'post fields', 'headers'] as $field_name) {
|
|
|
|
|
if (array_key_exists($field_name, $data)) {
|
|
|
|
|
// TODO: Replace the below workaround with the commented line when ZBX-22433 is merged.
|
|
|
|
|
// $form->getField(ucfirst($field_name))->asMultifieldTable()->fill($data[$field_name]);
|
|
|
|
|
$field = $step_form->getField(ucfirst($field_name));
|
|
|
|
|
$this->fillTableField($data[$field_name], $field);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$step_form->submit();
|
|
|
|
|
|
|
|
|
|
if ($expected === TEST_BAD) {
|
|
|
|
|
// There are step form level errors and scenario form level errors. They are checked differently.
|
|
|
|
|
$this->assertMessage(TEST_BAD, 'Cannot '.$action.' web scenario step', $data['error']);
|
|
|
|
|
$dialog->close();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$scenario_form->submit();
|
|
|
|
|
$this->assertMessage(TEST_GOOD, 'Web scenario updated');
|
|
|
|
|
|
|
|
|
|
// TODO: add logic to trim headers an variables after ZBX-22433 is merged.
|
|
|
|
|
if (array_key_exists('trim', $data)) {
|
|
|
|
|
$data['fields'] = array_map('trim', $data['fields']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($action === 'update') {
|
|
|
|
|
self::$update_step = $data['fields']['Name'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->query('link', $scenario)->waitUntilClickable()->one()->click();
|
|
|
|
|
$this->page->waitUntilReady();
|
|
|
|
|
|
|
|
|
|
$scenario_form->selectTab('Steps');
|
|
|
|
|
|
|
|
|
|
// Check values displayed in Steps table.
|
|
|
|
|
$step_row = $scenario_form->getField('Steps')->asTable()->findRow('Name', $data['fields']['Name']);
|
|
|
|
|
$this->assertEquals($data['fields']['id:url'], $step_row->getColumn('URL')->getText());
|
|
|
|
|
|
|
|
|
|
$column_mapping = [
|
|
|
|
|
'Required' => 'Required string',
|
|
|
|
|
'Status codes' => 'Required status codes'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
foreach (['Timeout' => '15s', 'Required' => '', 'Status codes' => ''] as $column => $value) {
|
|
|
|
|
$actual_field = ($column === 'Timeout') ? $column : $column_mapping[$column];
|
|
|
|
|
|
|
|
|
|
if (array_key_exists($actual_field, $data['fields'])) {
|
|
|
|
|
$value = $data['fields'][$actual_field];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->assertEquals($value, $step_row->getColumn($column)->getText());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check the values in the web scenario step configuration form.
|
|
|
|
|
$step_row->query('link', $data['fields']['Name'])->one()->click();
|
|
|
|
|
$step_form->invalidate();
|
|
|
|
|
|
|
|
|
|
$step_form->checkValue($data['fields']);
|
|
|
|
|
|
|
|
|
|
foreach (['variables', 'query fields', 'post fields', 'headers'] as $field_name) {
|
|
|
|
|
if (array_key_exists($field_name, $data)) {
|
|
|
|
|
// TODO: Replace the below workaround with a check via $table->checkValue() when ZBX-22433 is merged.
|
|
|
|
|
$field = $step_form->getField(ucfirst($field_name));
|
|
|
|
|
$this->checkTableField($field, $data[$field_name]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testFormWebScenarioStep_SimpleUpdate() {
|
|
|
|
|
$this->checkImpactlessAction('simple_update');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testFormWebScenarioStep_CancelCreate() {
|
|
|
|
|
$this->checkImpactlessAction('cancel_create');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testFormWebScenarioStep_CancelUpdate() {
|
|
|
|
|
$this->checkImpactlessAction('cancel_update');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testFormWebScenarioStep_CancelDelete() {
|
|
|
|
|
$this->checkImpactlessAction('cancel_delete');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check different action cancellation and update without applying any changes.
|
|
|
|
|
*
|
|
|
|
|
* @param string $action action to be checked
|
|
|
|
|
*/
|
|
|
|
|
protected function checkImpactlessAction($action) {
|
|
|
|
|
$old_hash = CDBHelper::getHash(self::SQL);
|
|
|
|
|
$scenario_form = $this->getScenarioFormOnStepsTab(self::UPDATE_SCENARIO);
|
|
|
|
|
$steps = $scenario_form->getField('Steps')->asTable();
|
|
|
|
|
|
|
|
|
|
if ($action === 'cancel_delete') {
|
|
|
|
|
$steps->findRow('Name', self::IMPACTLESS_STEP)->query('button:Remove')->one()->click();
|
|
|
|
|
$scenario_form->query('button:Cancel')->one()->click();
|
|
|
|
|
$this->page->waitUntilReady();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$open_step = ($action === 'cancel_create') ? 'button:Add' : 'link:'.self::IMPACTLESS_STEP;
|
|
|
|
|
$steps->query($open_step)->waitUntilClickable()->one()->click();
|
|
|
|
|
|
|
|
|
|
$dialog = COverlayDialogElement::find()->waitUntilReady()->one();
|
|
|
|
|
$step_form = $dialog->asForm();
|
|
|
|
|
|
|
|
|
|
if ($action === 'simple_update') {
|
|
|
|
|
$step_form->submit();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$values = [
|
|
|
|
|
'Name' => $action.' step',
|
|
|
|
|
'id:url' => 'http://'.$action.'.lv',
|
|
|
|
|
'Retrieve mode' => 'Headers'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$step_form->fill($values);
|
|
|
|
|
$dialog->query('button:Cancel')->one()->click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$dialog->ensureNotPresent();
|
|
|
|
|
|
|
|
|
|
$scenario_form->submit();
|
|
|
|
|
$this->page->waitUntilReady();
|
|
|
|
|
$this->assertMessage(TEST_GOOD, 'Web scenario updated');
|
|
|
|
|
}
|
|
|
|
|
$this->assertEquals($old_hash, CDBHelper::getHash(self::SQL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testFormWebScenarioStep_Remove() {
|
|
|
|
|
$form = $this->getScenarioFormOnStepsTab(self::UPDATE_SCENARIO);
|
|
|
|
|
|
|
|
|
|
$form->getField('Steps')->asTable()->findRow('Name', self::IMPACTLESS_STEP)->query('button:Remove')->one()->click();
|
|
|
|
|
$form->submit();
|
|
|
|
|
$this->page->waitUntilReady();
|
|
|
|
|
$this->assertMessage(TEST_GOOD, 'Web scenario updated');
|
|
|
|
|
|
|
|
|
|
$sql = 'SELECT httpstepid FROM httpstep WHERE name='.zbx_dbstr(self::IMPACTLESS_STEP).
|
|
|
|
|
' AND httptestid IN (SELECT httptestid FROM httptest WHERE name='.zbx_dbstr(self::UPDATE_SCENARIO).')';
|
|
|
|
|
$this->assertEquals(0, CDBHelper::getCount($sql));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function getStepUrlData() {
|
|
|
|
|
return [
|
|
|
|
|
// #0 Plain parsing of URL parameters.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'url' => 'https://intranet.zabbix.com/secure/admin.jspa?login=admin&password=s00p3r%24ecr3%26',
|
|
|
|
|
'parsed_query' => [
|
|
|
|
|
['name' => 'login', 'value' => 'admin'],
|
|
|
|
|
['name' => 'password', 'value' => 's00p3r$ecr3&']
|
|
|
|
|
],
|
|
|
|
|
'resulting_url' => 'https://intranet.zabbix.com/secure/admin.jspa'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #1 Unrelated existing and parsed query parameters.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'url' => 'https://intranet.zabbix.com/secure/admin.jspa?password=s00p3r%24ecr3%26',
|
|
|
|
|
'existing_query' => [
|
|
|
|
|
['name' => 'login', 'value' => 'admin']
|
|
|
|
|
],
|
|
|
|
|
'parsed_query' => [
|
|
|
|
|
['name' => 'login', 'value' => 'admin'],
|
|
|
|
|
['name' => 'password', 'value' => 's00p3r$ecr3&']
|
|
|
|
|
],
|
|
|
|
|
'resulting_url' => 'https://intranet.zabbix.com/secure/admin.jspa'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #2 Duplicate parameters should not be erased during parsing.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'url' => 'https://intranet.zabbix.com/secure/admin.jspa?login=user&password=a123%24bcd4%26',
|
|
|
|
|
'existing_query' => [
|
|
|
|
|
['name' => 'login', 'value' => 'admin'],
|
|
|
|
|
['name' => 'login', 'value' => 'user'],
|
|
|
|
|
['name' => 'password', 'value' => 'password']
|
|
|
|
|
],
|
|
|
|
|
'parsed_query' => [
|
|
|
|
|
['name' => 'login', 'value' => 'admin'],
|
|
|
|
|
['name' => 'login', 'value' => 'user'],
|
|
|
|
|
['name' => 'password', 'value' => 'password'],
|
|
|
|
|
['name' => 'login', 'value' => 'user'],
|
|
|
|
|
['name' => 'password', 'value' => 'a123$bcd4&']
|
|
|
|
|
],
|
|
|
|
|
'resulting_url' => 'https://intranet.zabbix.com/secure/admin.jspa'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #3 Invalid URL part removed during parsing.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'url' => 'http://www.zabbix.com/enterprise_ready#test',
|
|
|
|
|
'parsed_query' => [
|
|
|
|
|
['name' => '', 'value' => '']
|
|
|
|
|
],
|
|
|
|
|
'resulting_url' => 'http://www.zabbix.com/enterprise_ready'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #4 Empty query parameter name or value.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'url' => 'https://intranet.zabbix.com/secure/admin.jspa?=admin&password=',
|
|
|
|
|
'parsed_query' => [
|
|
|
|
|
['name' => '', 'value' => 'admin'],
|
|
|
|
|
['name' => 'password', 'value' => '']
|
|
|
|
|
],
|
|
|
|
|
'resulting_url' => 'https://intranet.zabbix.com/secure/admin.jspa'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #5 Improper query parameter in URL.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'url' => 'http://localhost/zabbix/index.php?test=%11',
|
|
|
|
|
'error' => "Failed to parse URL.\n\nURL is not properly encoded."
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider getStepUrlData
|
|
|
|
|
*/
|
|
|
|
|
public function testFormWebScenarioStep_ParseUrl($data) {
|
|
|
|
|
$step_form = $this->getStepForm(self::UPDATE_SCENARIO);
|
|
|
|
|
$url_field = $step_form->getField('id:url');
|
|
|
|
|
$url_field->fill($data['url']);
|
|
|
|
|
$query_table = $step_form->getField('Query fields');
|
|
|
|
|
|
|
|
|
|
// Fill in existing query fields if such are present in the data provider.
|
|
|
|
|
if (array_key_exists('existing_query', $data)) {
|
|
|
|
|
$this->fillTableField($data['existing_query'], $query_table);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$step_form->query('button:Parse')->one()->click();
|
|
|
|
|
|
|
|
|
|
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_GOOD) {
|
|
|
|
|
$query_table->invalidate();
|
|
|
|
|
$this->checkTableField($query_table, $data['parsed_query']);
|
|
|
|
|
$this->assertEquals($data['resulting_url'], $url_field->getValue());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$this->checkErrorDialog($data['error']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function getStepPostData() {
|
|
|
|
|
return [
|
|
|
|
|
// #0 Regular conversion to raw data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'post' => [
|
|
|
|
|
['name' => 'zab bix', 'value' => 'tes&t']
|
|
|
|
|
],
|
|
|
|
|
'result_raw' => 'zab%20bix=tes%26t'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #1 Other languages to raw data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'post' => [
|
|
|
|
|
['name' => 'тест', 'value' => '自分との戦い いつも負ける']
|
|
|
|
|
],
|
|
|
|
|
'result_raw' => '%D1%82%D0%B5%D1%81%D1%82=%E8%87%AA%E5%88%86%E3%81%A8%E3%81%AE%E6%88%A6%E3%81%84%20'.
|
|
|
|
|
'%E3%81%84%E3%81%A4%E3%82%82%E8%B2%A0%E3%81%91%E3%82%8B'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #2 Special symbols to raw data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'post' => [
|
|
|
|
|
['name' => '!@#$%^&*()', 'value' => '!@#$%^&*()']
|
|
|
|
|
],
|
|
|
|
|
'result_raw' => '!%40%23%24%25%5E%26*()=!%40%23%24%25%5E%26*()'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #3 Converting 2 post fields to raw data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'post' => [
|
|
|
|
|
['name' => 'zabbix', 'value' => 'test'],
|
|
|
|
|
['name' => '&Günter', 'value' => '']
|
|
|
|
|
],
|
|
|
|
|
'result_raw' => 'zabbix=test&%26G%C3%BCnter'
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #4 Converting raw data to 2 post fields.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'raw_data' => 'login=Admin&password={{password}.urlencode()}',
|
|
|
|
|
'result_post' => [
|
|
|
|
|
['name' => 'login', 'value' => 'Admin'],
|
|
|
|
|
['name' => 'password', 'value' => '{{password}.urlencode()}']
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #5 Converting raw data to post fields with encoding and without value.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'raw_data' => 'log+me+in%24&enter=Sign+in%26',
|
|
|
|
|
'result_post' => [
|
|
|
|
|
['name' => 'log me in$', 'value' => ''],
|
|
|
|
|
['name' => 'enter', 'value' => 'Sign in&']
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #6 Other languages from raw to post fields.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'raw_data' => '%E0%A4%B9%E0%A4%B0%E0%A4%B5%E0%A4%B2%E0%A5%87=tap%C4%B1ld%C4%B1',
|
|
|
|
|
'result_post' => [
|
|
|
|
|
['name' => 'हरवले', 'value' => 'tapıldı']
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #7 Missing name from raw data to form data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'raw_data' => '=value',
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nValues without names are not allowed in form fields."
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #8 Post data validation percent encoding pair is malformed.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'raw_data' => 'test=%11',
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nData is not properly encoded."
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #9 Non-existing character when converting from raw data to post data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'raw_data' => 'value=%00',
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nData is not properly encoded."
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #10 Unnecessary "=" symbol in raw data when converting to form data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'raw_data' => 'name=val=ue',
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nData is not properly encoded."
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #11 Non-unicode encodings when converting raw data to post data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'raw_data' => 'value=%EA%EE%EB%E1%E0%F1%EA%E8',
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nURIError: URI malformed"
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #12 Field name exceeds 255 symbols when converting raw data to post data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'raw_data' => '123456789012345'.STRING_255,
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nName of the form field should not exceed 255 characters."
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// #13 Missing name when converting post field to raw data.
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'expected' => TEST_BAD,
|
|
|
|
|
'post' => [
|
|
|
|
|
['name' => '', 'value' => '!@#$%^&*()']
|
|
|
|
|
],
|
|
|
|
|
'error' => "Cannot convert POST data:\n\nValues without names are not allowed in form fields."
|
|
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider getStepPostData
|
|
|
|
|
*/
|
|
|
|
|
public function testFormWebScenarioStep_ConvertPostData($data) {
|
|
|
|
|
$step_form = $this->getStepForm(self::UPDATE_SCENARIO);
|
|
|
|
|
$post_type = $step_form->getField('Post type');
|
|
|
|
|
|
|
|
|
|
if (array_key_exists('raw_data', $data)) {
|
|
|
|
|
$post_type->fill('Raw data');
|
|
|
|
|
$step_form->getField('Raw post')->fill($data['raw_data']);
|
|
|
|
|
|
|
|
|
|
$post_type->fill('Form data');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$post_table = $step_form->getField('Post fields');
|
|
|
|
|
$this->fillTableField($data['post'], $post_table);
|
|
|
|
|
$post_type->fill('Raw data');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CTestArrayHelper::get($data, 'expected', TEST_GOOD) === TEST_GOOD) {
|
|
|
|
|
if (array_key_exists('result_raw', $data)) {
|
|
|
|
|
$this->assertEquals($data['result_raw'], $step_form->getField('Raw post')->getValue());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$post_fields = $step_form->getField('Post fields');
|
|
|
|
|
$this->checkTableField($post_fields, $data['result_post']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$this->checkErrorDialog($data['error']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return web scenario step configuration form for the specified web scenario.
|
|
|
|
|
*
|
|
|
|
|
* @param string $scenario name of web scenario for which to open step configuration form
|
|
|
|
|
*
|
|
|
|
|
* @return CFormElement
|
|
|
|
|
*/
|
|
|
|
|
protected function getStepForm($scenario) {
|
|
|
|
|
$scenario_form = $this->getScenarioFormOnStepsTab($scenario);
|
|
|
|
|
$scenario_form->getField('Steps')->query('button:Add')->one()->click();
|
|
|
|
|
|
|
|
|
|
return COverlayDialogElement::find()->waitUntilReady()->one()->asForm();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return web scenario configuration form with opened Steps tab.
|
|
|
|
|
*
|
|
|
|
|
* @param string $scenario Name of the scenario to be opened
|
|
|
|
|
*
|
|
|
|
|
* @return CFormElement
|
|
|
|
|
*/
|
|
|
|
|
protected function getScenarioFormOnStepsTab($scenario) {
|
|
|
|
|
$this->page->login()->open('httpconf.php?filter_set=1&filter_hostids%5B0%5D='.self::HOSTID.'&context=host')
|
|
|
|
|
->waitUntilReady();
|
|
|
|
|
$this->query('link:'.$scenario)->waitUntilClickable()->one()->click();
|
|
|
|
|
$this->page->waitUntilReady();
|
|
|
|
|
|
|
|
|
|
$scenario_form = $this->query('name:webscenario_form')->asForm()->one();
|
|
|
|
|
$scenario_form->selectTab('Steps');
|
|
|
|
|
|
|
|
|
|
return $scenario_form;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check the content of the error dialog that appears when parsing URL or converting post data.
|
|
|
|
|
*
|
|
|
|
|
* @param string $error expected error message text
|
|
|
|
|
*/
|
|
|
|
|
protected function checkErrorDialog($error) {
|
|
|
|
|
$error_dialog = COverlayDialogElement::find()->all()->last()->waitUntilReady();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals('Error', $error_dialog->getTitle());
|
|
|
|
|
$this->assertEquals($error, $error_dialog->getContent()->getText());
|
|
|
|
|
$error_dialog->getFooter()->query('button:Ok')->one()->click();
|
|
|
|
|
$error_dialog->waitUntilNotPresent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compare values from corresponding value pair table with expected data.
|
|
|
|
|
*
|
|
|
|
|
* @param CElement $table_field value pair field object
|
|
|
|
|
* @param array $expected array with reference values
|
|
|
|
|
*/
|
|
|
|
|
protected function checkTableField($table_field, $expected) {
|
|
|
|
|
$obtained_fields = [];
|
|
|
|
|
$i = 0;
|
|
|
|
|
|
|
|
|
|
foreach ($table_field->query('class:form_row')->all() as $table_row) {
|
|
|
|
|
$obtained_fields[$i]['name'] = $table_row->query('xpath:(.//textarea)[1]')->one()->getValue();
|
|
|
|
|
|
|
|
|
|
if (array_key_exists('value', $expected[$i])) {
|
|
|
|
|
$obtained_fields[$i]['value'] = $table_row->query('xpath:(.//textarea)[2]')->one()->getValue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->assertEquals($expected, $obtained_fields);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fill the corresponding value pair table.
|
|
|
|
|
*
|
|
|
|
|
* @param array $input_data values to be filled in
|
|
|
|
|
* @param string $table_field name of the value pair field
|
|
|
|
|
*/
|
|
|
|
|
protected function fillTableField($input_data, $table_field) {
|
|
|
|
|
$count = count($input_data);
|
|
|
|
|
$add_button = $table_field->query('button:Add')->one();
|
|
|
|
|
|
|
|
|
|
$i = 1;
|
|
|
|
|
foreach ($input_data as $row) {
|
|
|
|
|
// Add row in field table if required.
|
|
|
|
|
if ($table_field->query('class:form_row')->all()->count() !== $count) {
|
|
|
|
|
$add_button->click();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: xpath quotes should be fixed after git-hook improvements in DEV-2396.
|
|
|
|
|
$table_field->query("xpath:(.//tr[".$i."]//textarea)[1]")->one()->fill($row['name']);
|
|
|
|
|
|
|
|
|
|
if (array_key_exists('value', $row)) {
|
|
|
|
|
$table_field->query("xpath:(.//tr[".$i."]//textarea)[2]")->one()->fill($row['value']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|