From 49736322887029b409ff177eafca9581c6622e83 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Fri, 5 Feb 2016 23:48:57 +0100 Subject: [PATCH 01/12] [ticket/14315] Only add role options specified for each group PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 2 ++ phpBB/includes/acp/auth.php | 1 + 2 files changed, 3 insertions(+) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 347da3181e..75e76b157d 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -46,7 +46,9 @@ <div class="dropdown hidden"> <ul class="dropdown-contents" id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" > {% for role in loops.role_options %} + {% if role.UG_ID == p_mask.f_mask.UG_ID %} <li data-id="{{ role.ID }}" data-target-id="advanced{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" data-title="{{ role.TITLE }}"{% if role.SELECTED == true %} data-selected="{{ role.SELECTED }}"{% endif %}>{{ role.ROLE_NAME }}</li> + {% endif %} {% endfor %} </ul> </div> diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 11478842d7..a3972158a2 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -477,6 +477,7 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars('role_options', array( 'ID' => $role_id, + 'UG_ID' => $ug_id, 'ROLE_NAME' => $role_name, 'TITLE' => $role_description, 'SELECTED' => $role_id == $current_role_id, From eab1b1ad11ae2e42cf4f6c3af9f7171d6dd0837b Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Fri, 5 Feb 2016 23:59:19 +0100 Subject: [PATCH 02/12] [ticket/14315] Correctly set default values and reset values The permissions tooltip javascript failed at correctly passing the default values to the page. The same applied to the display_mask() method in includes/acp/auth.php. PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 2 +- phpBB/adm/style/tooltip.js | 32 ++++++++++++++-------------- phpBB/includes/acp/auth.php | 8 +++---- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 75e76b157d..aa18a40cb7 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -52,7 +52,7 @@ {% endfor %} </ul> </div> - <input type="hidden" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]"{% if S_ROLE_ID %}value="{{ S_ROLE_ID }}"{% endif %} /> + <input type="hidden" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]"{% if p_mask.f_mask.S_ROLE_ID %}value="{{ p_mask.f_mask.S_ROLE_ID }}"{% endif %} /> </div> </dd> {% else %} diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 68964034f0..3abeefbffe 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -141,20 +141,32 @@ phpbb.positionTooltip = function ($element) { */ phpbb.prepareRolesDropdown = function () { var $options = $('.roles-options li'); - var $rolesOptions = $options.closest('.roles-options'); - var $span = $rolesOptions.children('span'); // Prepare highlighting of select options and settings update $options.each(function () { var $this = $(this); + var $rolesOptions = $this.closest('.roles-options'); + var $span = $rolesOptions.children('span'); // Correctly show selected option if (typeof $this.attr('data-selected') !== 'undefined') { - $rolesOptions.closest('.roles-options') + $rolesOptions .children('span') .text($this.text()) .attr('data-default', $this.text()) .attr('data-default-val', $this.attr('data-id')); + + // Save default text of drop down if there is no default set yet + if (typeof $span.attr('data-default') === 'undefined') { + $span.attr('data-default', $span.text()); + } + + // Prepare resetting drop down on form reset + $this.closest('form').on('reset', function () { + $span.text($span.attr('data-default')); + $rolesOptions.children('input[type=hidden]') + .val($span.attr('data-default-val')); + }); } $this.on('mouseover', function () { @@ -163,6 +175,7 @@ phpbb.prepareRolesDropdown = function () { $this.addClass('roles-highlight'); }).on('click', function () { var $this = $(this); + var $rolesOptions = $this.closest('.roles-options'); // Update settings set_role_settings($this.attr('data-id'), $this.attr('data-target-id')); @@ -178,19 +191,6 @@ phpbb.prepareRolesDropdown = function () { $('body').trigger('click'); }); }); - - // Save default text of drop down if there is no default set yet - if (typeof $span.attr('data-default') === 'undefined') { - $span.attr('data-default', $span.text()); - } - - // Prepare resetting drop down on form reset - $options.closest('form').on('reset', function () { - $span.text($span.attr('data-default')); - $rolesOptions.children('input[type=hidden]') - .val($span.attr('data-id')); - }); - }; // Run onload functions for RolesDropdown and tooltips diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index a3972158a2..755923ff8c 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -466,9 +466,6 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - // Output current role id to template - $template->assign_var('S_ROLE_ID', $current_role_id); - @reset($roles); while (list($role_id, $role_row) = each($roles)) { @@ -506,8 +503,9 @@ class auth_admin extends \phpbb\auth\auth 'NAME' => $ug_names_ary[$ug_id], 'UG_ID' => $ug_id, 'S_CUSTOM' => $s_custom_permissions, - 'FORUM_ID' => $forum_id) - ); + 'FORUM_ID' => $forum_id, + 'S_ROLE_ID' => $current_role_id, + )); $this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace); From 4cfba8f3a40c424d831b6034bdf1dc4975822406 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Sat, 6 Feb 2016 09:33:33 +0100 Subject: [PATCH 03/12] [ticket/14315] Build role options for each permission group Previously all role options were put into one array. This required filtering the options. Instead, these are now passed to the template via template loops. PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 6 ++---- phpBB/includes/acp/auth.php | 9 ++++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index aa18a40cb7..721fc42473 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -39,16 +39,14 @@ </div> <dl class="permissions-simple"> <dt style="width: 20%"><label for="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}">{L_ROLE}{L_COLON}</label></dt> - {% if role_options %} + {% if p_mask.f_mask.role_options %} <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 20%"> <div class="dropdown-container dropdown-button-control roles-options" data-alt-text="{LA_ROLE_DESCRIPTION}"> <span title="Roles" class="button icon-button tools-icon dropdown-trigger dropdown-select">{L_NO_ROLE_ASSIGNED}</span> <div class="dropdown hidden"> <ul class="dropdown-contents" id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" > - {% for role in loops.role_options %} - {% if role.UG_ID == p_mask.f_mask.UG_ID %} + {% for role in p_mask.f_mask.role_options %} <li data-id="{{ role.ID }}" data-target-id="advanced{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" data-title="{{ role.TITLE }}"{% if role.SELECTED == true %} data-selected="{{ role.SELECTED }}"{% endif %}>{{ role.ROLE_NAME }}</li> - {% endif %} {% endfor %} </ul> </div> diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 755923ff8c..e1f7fb646f 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -466,19 +466,20 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + $role_options = array(); + @reset($roles); while (list($role_id, $role_row) = each($roles)) { $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - $template->assign_block_vars('role_options', array( + $role_options[] = array( 'ID' => $role_id, - 'UG_ID' => $ug_id, 'ROLE_NAME' => $role_name, 'TITLE' => $role_description, 'SELECTED' => $role_id == $current_role_id, - )); + ); } if (!$current_role_id && $mode != 'view') @@ -507,6 +508,8 @@ class auth_admin extends \phpbb\auth\auth 'S_ROLE_ID' => $current_role_id, )); + $template->assign_block_vars_array($tpl_pmask . '.' . $tpl_fmask . '.role_options', $role_options); + $this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace); unset($content_array[$ug_id]); From 0a1604a5360a8fe02b77f6fc4dbb18f5b0d3915f Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Tue, 16 Feb 2016 17:05:41 +0100 Subject: [PATCH 04/12] [ticket/14315] Apply roles options format for multiple forums too PHPBB3-14315 --- phpBB/includes/acp/auth.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index e1f7fb646f..31471f8611 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -553,8 +553,7 @@ class auth_admin extends \phpbb\auth\auth // Build role dropdown options $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; - // Output current role id to template - $template->assign_var('S_ROLE_ID', $current_role_id); + $role_options = array(); @reset($roles); while (list($role_id, $role_row) = each($roles)) @@ -562,12 +561,12 @@ class auth_admin extends \phpbb\auth\auth $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; - $template->assign_block_vars('role_options', array( + $role_options[] = array( 'ID' => $role_id, 'ROLE_NAME' => $role_name, 'TITLE' => $role_description, 'SELECTED' => $role_id == $current_role_id, - )); + ); } if (!$current_role_id && $mode != 'view') @@ -596,6 +595,8 @@ class auth_admin extends \phpbb\auth\auth 'FORUM_ID' => $forum_id) ); + $template->assign_block_vars_array($tpl_pmask . '.' . $tpl_fmask . '.role_options', $role_options); + $this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace); } From 32815faa3357e307a7459a88baabeb2c9cd5de0d Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Tue, 16 Feb 2016 17:06:07 +0100 Subject: [PATCH 05/12] [ticket/14315] Tweak location of drop-down PHPBB3-14315 --- phpBB/adm/style/admin.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 4bb9922d56..e537e970a3 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2471,7 +2471,7 @@ fieldset.permissions .padding { .roles-options > .dropdown { left: auto; - top: 3em; + top: 3.2em; width: 250px; } From 6f41fcb3d615557c79892bc8d0c43d523a2c1959 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Tue, 16 Feb 2016 17:32:33 +0100 Subject: [PATCH 06/12] [ticket/14315] Add back roles select for disable javascript The javascript will hide the old select and show the version using the span and showing the tooltips. PHPBB3-14315 --- phpBB/adm/style/admin.css | 2 +- phpBB/adm/style/permission_mask.html | 1 + phpBB/adm/style/tooltip.js | 4 ++++ phpBB/includes/acp/auth.php | 24 ++++++++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index e537e970a3..e1668bf70b 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -2489,7 +2489,7 @@ fieldset.permissions .padding { border-radius: 3px; padding: 4px; width: 250px; - display: block; + display: none; background: url('../images/arrow_down.gif') no-repeat 245px .7em; } diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 721fc42473..cddcac170f 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -42,6 +42,7 @@ {% if p_mask.f_mask.role_options %} <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 20%"> <div class="dropdown-container dropdown-button-control roles-options" data-alt-text="{LA_ROLE_DESCRIPTION}"> + <select id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]" onchange="set_role_settings(this.options[selectedIndex].value, 'advanced{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}'); init_colours('{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}')">{p_mask.f_mask.S_ROLE_OPTIONS}</select> <span title="Roles" class="button icon-button tools-icon dropdown-trigger dropdown-select">{L_NO_ROLE_ASSIGNED}</span> <div class="dropdown hidden"> <ul class="dropdown-contents" id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" > diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 3abeefbffe..b38418876d 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -142,6 +142,10 @@ phpbb.positionTooltip = function ($element) { phpbb.prepareRolesDropdown = function () { var $options = $('.roles-options li'); + // Display span and hide select + $('.roles-options > span').css('display', 'block'); + $('.roles-options > select').hide(); + // Prepare highlighting of select options and settings update $options.each(function () { var $this = $(this); diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 31471f8611..b36b900396 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -468,12 +468,18 @@ class auth_admin extends \phpbb\auth\auth $role_options = array(); + $s_role_options = ''; + $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + @reset($roles); while (list($role_id, $role_row) = each($roles)) { $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + $title = ($role_description) ? ' title="' . $role_description . '"' : ''; + $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; + $role_options[] = array( 'ID' => $role_id, 'ROLE_NAME' => $role_name, @@ -482,6 +488,11 @@ class auth_admin extends \phpbb\auth\auth ); } + if ($s_role_options) + { + $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options; + } + if (!$current_role_id && $mode != 'view') { $s_custom_permissions = false; @@ -503,6 +514,7 @@ class auth_admin extends \phpbb\auth\auth $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( 'NAME' => $ug_names_ary[$ug_id], 'UG_ID' => $ug_id, + 'S_ROLE_OPTIONS' => $s_role_options, 'S_CUSTOM' => $s_custom_permissions, 'FORUM_ID' => $forum_id, 'S_ROLE_ID' => $current_role_id, @@ -555,12 +567,18 @@ class auth_admin extends \phpbb\auth\auth $role_options = array(); + $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + $s_role_options = ''; + @reset($roles); while (list($role_id, $role_row) = each($roles)) { $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + $title = ($role_description) ? ' title="' . $role_description . '"' : ''; + $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; + $role_options[] = array( 'ID' => $role_id, 'ROLE_NAME' => $role_name, @@ -569,6 +587,11 @@ class auth_admin extends \phpbb\auth\auth ); } + if ($s_role_options) + { + $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options; + } + if (!$current_role_id && $mode != 'view') { $s_custom_permissions = false; @@ -592,6 +615,7 @@ class auth_admin extends \phpbb\auth\auth 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], 'S_CUSTOM' => $s_custom_permissions, 'UG_ID' => $ug_id, + 'S_ROLE_OPTIONS' => $s_role_options, 'FORUM_ID' => $forum_id) ); From 845639ba371e0aacb60f760851c9c6b1cf6e9bd6 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Tue, 16 Feb 2016 22:45:31 +0100 Subject: [PATCH 07/12] [ticket/14315] Add more functionality to ui test cases PHPBB3-14315 --- tests/test_framework/phpbb_ui_test_case.php | 208 ++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php index 8b60096081..f9f4c516e6 100644 --- a/tests/test_framework/phpbb_ui_test_case.php +++ b/tests/test_framework/phpbb_ui_test_case.php @@ -34,6 +34,18 @@ class phpbb_ui_test_case extends phpbb_test_case static protected $install_success = false; static protected $db; + /** + * Session ID for current test's session (each test makes its own) + * @var string + */ + protected $sid; + + /** + * Language array used by phpBB + * @var array + */ + protected $lang = array(); + static public function setUpBeforeClass() { parent::setUpBeforeClass(); @@ -87,6 +99,11 @@ class phpbb_ui_test_case extends phpbb_test_case { $this->fail('Installing phpBB has failed.'); } + + // Clear the language array so that things + // that were added in other tests are gone + $this->lang = array(); + $this->add_lang('common'); } protected function tearDown() @@ -258,4 +275,195 @@ class phpbb_ui_test_case extends phpbb_test_case } return self::$db; } + + /** + * Login to the ACP + * You must run login() before calling this. + */ + protected function admin_login($username = 'admin') + { + $this->add_lang('acp/common'); + + // Requires login first! + if (empty($this->sid)) + { + $this->fail('$this->sid is empty. Make sure you call login() before admin_login()'); + return; + } + + $this->visit('adm/index.php?sid=' . $this->sid); + $this->assertContains($this->lang('LOGIN_ADMIN_CONFIRM'), self::$webDriver->getPageSource()); + + self::find_element('cssSelector', 'input[name=username]')->clear()->sendKeys($username); + self::find_element('cssSelector', 'input[type=password]')->sendKeys($username . $username); + self::find_element('cssSelector', 'input[name=login]')->click(); + $this->assertContains($this->lang('ADMIN_PANEL'), $this->find_element('cssSelector', 'h1')->getText()); + + $cookies = self::$webDriver->manage()->getCookies(); + + // The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie + foreach ($cookies as $cookie) + { + if (substr($cookie['name'], -4) == '_sid') + { + $this->sid = $cookie['value']; + } + } + } + + protected function add_lang($lang_file) + { + if (is_array($lang_file)) + { + foreach ($lang_file as $file) + { + $this->add_lang($file); + } + } + + $lang_path = __DIR__ . "/../../phpBB/language/en/$lang_file.php"; + + $lang = array(); + + if (file_exists($lang_path)) + { + include($lang_path); + } + + $this->lang = array_merge($this->lang, $lang); + } + + protected function add_lang_ext($ext_name, $lang_file) + { + if (is_array($lang_file)) + { + foreach ($lang_file as $file) + { + $this->add_lang_ext($ext_name, $file); + } + + return; + } + + $lang_path = __DIR__ . "/../../phpBB/ext/{$ext_name}/language/en/$lang_file.php"; + + $lang = array(); + + if (file_exists($lang_path)) + { + include($lang_path); + } + + $this->lang = array_merge($this->lang, $lang); + } + + protected function lang() + { + $args = func_get_args(); + $key = $args[0]; + + if (empty($this->lang[$key])) + { + throw new RuntimeException('Language key "' . $key . '" could not be found.'); + } + + $args[0] = $this->lang[$key]; + + return call_user_func_array('sprintf', $args); + } + + /** + * assertContains for language strings + * + * @param string $needle Search string + * @param string $haystack Search this + * @param string $message Optional failure message + */ + public function assertContainsLang($needle, $haystack, $message = null) + { + $this->assertContains(html_entity_decode($this->lang($needle), ENT_QUOTES), $haystack, $message); + } + + /** + * assertNotContains for language strings + * + * @param string $needle Search string + * @param string $haystack Search this + * @param string $message Optional failure message + */ + public function assertNotContainsLang($needle, $haystack, $message = null) + { + $this->assertNotContains(html_entity_decode($this->lang($needle), ENT_QUOTES), $haystack, $message); + } + + protected function login($username = 'admin') + { + $this->add_lang('ucp'); + + $this->visit('ucp.php'); + $this->assertContains($this->lang('LOGIN_EXPLAIN_UCP'), self::$webDriver->getPageSource()); + + self::find_element('cssSelector', 'input[name=username]')->sendKeys($username); + self::find_element('cssSelector', 'input[name=password]')->sendKeys($username . $username); + self::find_element('cssSelector', 'input[name=login]')->click(); + $this->assertNotContains($this->lang('LOGIN'), $this->find_element('className', 'navbar')->getText()); + + $cookies = self::$webDriver->manage()->getCookies(); + + // The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie + foreach ($cookies as $cookie) + { + if (substr($cookie['name'], -4) == '_sid') + { + $this->sid = $cookie['value']; + } + } + } + + /** + * Take screenshot. Can be used for debug purposes. + * + * @param \Facebook\WebDriver\Remote\RemoteWebElement $element + * @return string Element screenshot path + * @throws Exception When screenshot can't be created + */ + public function takeScreenshot($element = null) { + // Change the Path to your own settings + $screenshot = time() . ".png"; + + // Change the driver instance + self::$webDriver->takeScreenshot($screenshot); + if(!file_exists($screenshot)) { + throw new Exception('Could not save screenshot'); + } + + if( ! (bool) $element) { + return $screenshot; + } + + $element_screenshot = time() . ".png"; // Change the path here as well + + $element_width = $element->getSize()->getWidth(); + $element_height = $element->getSize()->getHeight(); + + $element_src_x = $element->getLocation()->getX(); + $element_src_y = $element->getLocation()->getY(); + + // Create image instances + $src = imagecreatefrompng($screenshot); + $dest = imagecreatetruecolor($element_width, $element_height); + + // Copy + imagecopy($dest, $src, 0, 0, $element_src_x, $element_src_y, $element_width, $element_height); + + imagepng($dest, $element_screenshot); + + // unlink($screenshot); // unlink function might be restricted in mac os x. + + if( ! file_exists($element_screenshot)) { + throw new Exception('Could not save element screenshot'); + } + + return $element_screenshot; + } } From d429fd03bfaf648a685519dfc7383152611a08e7 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Tue, 16 Feb 2016 22:46:03 +0100 Subject: [PATCH 08/12] [ticket/14315] Add tests for setting permission roles using javascript PHPBB3-14315 --- tests/ui/permission_roles_test.php | 89 ++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/ui/permission_roles_test.php diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php new file mode 100644 index 0000000000..a688680028 --- /dev/null +++ b/tests/ui/permission_roles_test.php @@ -0,0 +1,89 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @group ui +*/ +class permission_roles_test extends phpbb_ui_test_case +{ + + public function test_quick_links() + { + $this->login(); + $this->admin_login(); + $this->add_lang('acp/permissions'); + $this->visit('adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid); + + // Select forums + $elements = self::find_element('cssSelector', 'select[id=forum]') + ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); + foreach ($elements as $element) + { + $element->click(); + } + self::find_element('cssSelector', 'form[id=select_victim]') + ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=submit]')) + ->click(); + + // Select administrators and guests + $groups_form = self::find_element('cssSelector', 'form[id=groups]'); + $elements = $groups_form + ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('select')) + ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); + + foreach ($elements as $element) + { + if ($element->getText() === 'Administrators' || $element->getText() === 'Guests') + { + $element->click(); + } + } + $groups_form->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[name=submit_edit_options]'))->click(); + + $first_fieldset = self::find_element('cssSelector', '#perm11'); + $this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); + $first_fieldset + ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle')) + ->click(); + $this->assertEquals('block', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); + $lis = $first_fieldset + ->findElements(\Facebook\WebDriver\WebDriverBy::cssSelector('ul > li')); + + foreach ($lis as $li) + { + if ($li->getAttribute('data-id') == 18) + { + $li->click(); + + break; + } + } + $this->assertEquals('none', $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); + $this->assertEquals(18, $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); + $this->assertEquals($this->lang('ROLE_FORUM_LIMITED'), $first_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); + + // Check that admin settings didn't get changed + $second_fieldset = self::find_element('cssSelector', '#perm10'); + $this->assertEquals('none', $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); + // Full access = 14 + $this->assertEquals(14, $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); + $this->assertEquals($this->lang('ROLE_FORUM_FULL'), $second_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); + + // Check that category settings were not modified + $category_fieldset = self::find_element('cssSelector', '#perm00'); + $this->assertEquals('none', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('div.dropdown'))->getCSSValue('display')); + // No settings + $this->assertEquals('', $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=hidden]'))->getAttribute('value')); + $this->assertEquals($this->lang('NO_ROLE_ASSIGNED'), $category_fieldset->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('span.dropdown-toggle'))->getText()); + } +} From 620a8622660c5a00f56ce686e397ed09d9cd4039 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Wed, 17 Feb 2016 12:56:19 +0100 Subject: [PATCH 09/12] [ticket/14315] Add functional tests for permission roles and fix non-js Without JS the settings were not applied due to duplicate input names. PHPBB3-14315 --- phpBB/adm/style/permission_mask.html | 4 +- phpBB/adm/style/tooltip.js | 7 ++ tests/functional/permission_roles_test.php | 86 ++++++++++++++++++++++ tests/ui/permission_roles_test.php | 4 +- 4 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 tests/functional/permission_roles_test.php diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index cddcac170f..017d29d832 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -42,7 +42,7 @@ {% if p_mask.f_mask.role_options %} <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 20%"> <div class="dropdown-container dropdown-button-control roles-options" data-alt-text="{LA_ROLE_DESCRIPTION}"> - <select id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]" onchange="set_role_settings(this.options[selectedIndex].value, 'advanced{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}'); init_colours('{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}')">{p_mask.f_mask.S_ROLE_OPTIONS}</select> + <select id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]">{p_mask.f_mask.S_ROLE_OPTIONS}</select> <span title="Roles" class="button icon-button tools-icon dropdown-trigger dropdown-select">{L_NO_ROLE_ASSIGNED}</span> <div class="dropdown hidden"> <ul class="dropdown-contents" id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" > @@ -51,7 +51,7 @@ {% endfor %} </ul> </div> - <input type="hidden" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]"{% if p_mask.f_mask.S_ROLE_ID %}value="{{ p_mask.f_mask.S_ROLE_ID }}"{% endif %} /> + <input type="hidden" data-name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]"{% if p_mask.f_mask.S_ROLE_ID %}value="{{ p_mask.f_mask.S_ROLE_ID }}"{% endif %} /> </div> </dd> {% else %} diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index b38418876d..65773ae14f 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -145,6 +145,13 @@ phpbb.prepareRolesDropdown = function () { // Display span and hide select $('.roles-options > span').css('display', 'block'); $('.roles-options > select').hide(); + $('.roles-options > input[type=hidden]').each(function () { + var $this = $(this); + + if ($this.attr('data-name') && !$this.attr('name')) { + $this.attr('name', $this.attr('data-name')); + } + }); // Prepare highlighting of select options and settings update $options.each(function () { diff --git a/tests/functional/permission_roles_test.php b/tests/functional/permission_roles_test.php new file mode 100644 index 0000000000..82d5be68c3 --- /dev/null +++ b/tests/functional/permission_roles_test.php @@ -0,0 +1,86 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +require_once __DIR__ . '/../../phpBB/includes/functions.php'; + +/** +* @group functional +*/ +class functional_permission_roles_test extends phpbb_functional_test_case +{ + public function data_permission_roles() + { + return array( + array( + array(0, 14), + array(17, 17), + array( + 'role[5][1]' => 14, + ) + ), + array( + array(14, 14), + array(17, 17), + array( + 'role[5][1]' => 0, + ) + ), + array( + array(0, 14), + array(17, 17) + ), + ); + } + /** + * @dataProvider data_permission_roles + */ + public function test_permission_roles($admin_roles, $guest_roles, $set_values = array()) + { + $this->login(); + $this->admin_login(); + $this->add_lang('acp/permissions'); + $crawler = self::request('GET', 'adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid); + + // Select forums + $form = $crawler->filter('form[id=select_victim]')->form(); + $form['forum_id']->setValue(array(1,2)); + $crawler = self::$client->submit($form); + + // Select administrators and guests + $groups_form = $crawler->filter('form[id=groups]')->form(); + $groups_form['group_id']->setValue(array(1,5)); + + $crawler = self::submit($groups_form); + $form = $crawler->filter('form')->form(); + $values = $form->getValues(); + + // Check default settings + $this->assertEquals($admin_roles[0], $values['role[5][1]']); + $this->assertEquals($admin_roles[1], $values['role[5][2]']); + $this->assertEquals($guest_roles[0], $values['role[1][1]']); + $this->assertEquals($guest_roles[1], $values['role[1][2]']); + + // Set admin to full access on category + foreach ($set_values as $key => $value) + { + $form[$key]->setValue($value); + } + + $form_values = $form->getValues(); + $form_values['action[apply_all_permissions]'] = true; + $crawler = self::request('POST', 'adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid, $form_values); + $this->assertContainsLang('AUTH_UPDATED', $crawler->text()); + + $this->logout(); + } +} diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php index a688680028..fbd0750785 100644 --- a/tests/ui/permission_roles_test.php +++ b/tests/ui/permission_roles_test.php @@ -14,10 +14,10 @@ /** * @group ui */ -class permission_roles_test extends phpbb_ui_test_case +class ui_permission_roles_test extends phpbb_ui_test_case { - public function test_quick_links() + public function test_permission_roles() { $this->login(); $this->admin_login(); From a75885bd85d57401904055366c18733ac84b323a Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Wed, 17 Feb 2016 13:26:35 +0100 Subject: [PATCH 10/12] [ticket/14315] Add logout to ui tests and use in permissions role test PHPBB3-14315 --- tests/test_framework/phpbb_ui_test_case.php | 10 ++++++++++ tests/ui/permission_roles_test.php | 1 + 2 files changed, 11 insertions(+) diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php index f9f4c516e6..7e87b63b97 100644 --- a/tests/test_framework/phpbb_ui_test_case.php +++ b/tests/test_framework/phpbb_ui_test_case.php @@ -276,6 +276,16 @@ class phpbb_ui_test_case extends phpbb_test_case return self::$db; } + protected function logout() + { + $this->add_lang('ucp'); + + $this->visit('ucp.php?sid=' . $this->sid . '&mode=logout'); + $this->assertContains($this->lang('REGISTER'), self::$webDriver->getPageSource()); + unset($this->sid); + + } + /** * Login to the ACP * You must run login() before calling this. diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php index fbd0750785..8d704606bf 100644 --- a/tests/ui/permission_roles_test.php +++ b/tests/ui/permission_roles_test.php @@ -19,6 +19,7 @@ class ui_permission_roles_test extends phpbb_ui_test_case public function test_permission_roles() { + $this->logout(); $this->login(); $this->admin_login(); $this->add_lang('acp/permissions'); From 7c96d0abcd2b41b0c76396a10da92dc94b5274bb Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Wed, 17 Feb 2016 13:47:51 +0100 Subject: [PATCH 11/12] [ticket/14315] Use proper ID selectors in ui test PHPBB3-14315 --- tests/ui/permission_roles_test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php index 8d704606bf..3bc35c5b68 100644 --- a/tests/ui/permission_roles_test.php +++ b/tests/ui/permission_roles_test.php @@ -26,18 +26,18 @@ class ui_permission_roles_test extends phpbb_ui_test_case $this->visit('adm/index.php?i=acp_permissions&mode=setting_forum_local&sid=' . $this->sid); // Select forums - $elements = self::find_element('cssSelector', 'select[id=forum]') + $elements = self::find_element('cssSelector', 'select#forum') ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); foreach ($elements as $element) { $element->click(); } - self::find_element('cssSelector', 'form[id=select_victim]') + self::find_element('cssSelector', 'form#select_victim') ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('input[type=submit]')) ->click(); // Select administrators and guests - $groups_form = self::find_element('cssSelector', 'form[id=groups]'); + $groups_form = self::find_element('cssSelector', 'form#groups'); $elements = $groups_form ->findElement(\Facebook\WebDriver\WebDriverBy::cssSelector('select')) ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); From 7d41fe01362d7752ca64981791b56b5133d39848 Mon Sep 17 00:00:00 2001 From: Marc Alexander <admin@m-a-styles.de> Date: Wed, 17 Feb 2016 14:11:27 +0100 Subject: [PATCH 12/12] [ticket/14315] Properly get sid from cookies and simplify take_screenshot PHPBB3-14315 --- tests/test_framework/phpbb_ui_test_case.php | 51 ++++++--------------- tests/ui/permission_roles_test.php | 2 +- 2 files changed, 16 insertions(+), 37 deletions(-) diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php index 7e87b63b97..9bb89781a1 100644 --- a/tests/test_framework/phpbb_ui_test_case.php +++ b/tests/test_framework/phpbb_ui_test_case.php @@ -280,6 +280,11 @@ class phpbb_ui_test_case extends phpbb_test_case { $this->add_lang('ucp'); + if (empty($this->sid)) + { + return; + } + $this->visit('ucp.php?sid=' . $this->sid . '&mode=logout'); $this->assertContains($this->lang('REGISTER'), self::$webDriver->getPageSource()); unset($this->sid); @@ -301,6 +306,8 @@ class phpbb_ui_test_case extends phpbb_test_case return; } + self::$webDriver->manage()->deleteAllCookies(); + $this->visit('adm/index.php?sid=' . $this->sid); $this->assertContains($this->lang('LOGIN_ADMIN_CONFIRM'), self::$webDriver->getPageSource()); @@ -317,8 +324,12 @@ class phpbb_ui_test_case extends phpbb_test_case if (substr($cookie['name'], -4) == '_sid') { $this->sid = $cookie['value']; + + break; } } + + $this->assertNotEmpty($this->sid); } protected function add_lang($lang_file) @@ -428,52 +439,20 @@ class phpbb_ui_test_case extends phpbb_test_case $this->sid = $cookie['value']; } } + + $this->assertNotEmpty($this->sid); } /** * Take screenshot. Can be used for debug purposes. * - * @param \Facebook\WebDriver\Remote\RemoteWebElement $element - * @return string Element screenshot path * @throws Exception When screenshot can't be created */ - public function takeScreenshot($element = null) { + public function take_screenshot() + { // Change the Path to your own settings $screenshot = time() . ".png"; - // Change the driver instance self::$webDriver->takeScreenshot($screenshot); - if(!file_exists($screenshot)) { - throw new Exception('Could not save screenshot'); - } - - if( ! (bool) $element) { - return $screenshot; - } - - $element_screenshot = time() . ".png"; // Change the path here as well - - $element_width = $element->getSize()->getWidth(); - $element_height = $element->getSize()->getHeight(); - - $element_src_x = $element->getLocation()->getX(); - $element_src_y = $element->getLocation()->getY(); - - // Create image instances - $src = imagecreatefrompng($screenshot); - $dest = imagecreatetruecolor($element_width, $element_height); - - // Copy - imagecopy($dest, $src, 0, 0, $element_src_x, $element_src_y, $element_width, $element_height); - - imagepng($dest, $element_screenshot); - - // unlink($screenshot); // unlink function might be restricted in mac os x. - - if( ! file_exists($element_screenshot)) { - throw new Exception('Could not save element screenshot'); - } - - return $element_screenshot; } } diff --git a/tests/ui/permission_roles_test.php b/tests/ui/permission_roles_test.php index 3bc35c5b68..3501124fc1 100644 --- a/tests/ui/permission_roles_test.php +++ b/tests/ui/permission_roles_test.php @@ -19,7 +19,6 @@ class ui_permission_roles_test extends phpbb_ui_test_case public function test_permission_roles() { - $this->logout(); $this->login(); $this->admin_login(); $this->add_lang('acp/permissions'); @@ -28,6 +27,7 @@ class ui_permission_roles_test extends phpbb_ui_test_case // Select forums $elements = self::find_element('cssSelector', 'select#forum') ->findElements(\Facebook\WebDriver\WebDriverBy::tagName('option')); + foreach ($elements as $element) { $element->click();