diff --git a/horizon/static/horizon/js/horizon.selenium.js b/horizon/static/horizon/js/horizon.selenium.js new file mode 100644 index 0000000000..8d43526155 --- /dev/null +++ b/horizon/static/horizon/js/horizon.selenium.js @@ -0,0 +1,73 @@ +/* Copyright (c) 2015 Mirantis, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain + a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + License for the specific language governing permissions and limitations + under the License. +*/ + +/* + NOTE(tsufiev): the purpose of this code is to mark the titles of expanded + dashboards and panel groups with special 'selenium-active' class that + integration tests can use to understand what dashboard/panel group is + currently open (and whether or not it needs to click it to proceed to some + other dashboard/panel group). The need for this code arises from 2 facts: + * since https://review.openstack.org/#/c/209259/ sidebar's expand/collapse + behavior doesn't rely on JS code (pure CSS instead) - which is good; + * to match dashboard/panel group header _before_ the 'li.panel-collapse.in' + we need '!' selector which will be supported only in CSS4 (not going soon). + */ +horizon.selenium = { +}; + +horizon.addInitFunction(horizon.selenium.init = function() { + var $activeEntry = $('li.openstack-dashboard.active > ul.panel-collapse.in'); + var dashboardLoc = 'li.openstack-dashboard'; + var groupLoc = 'li.nav-header.panel'; + var activeCls = 'selenium-active'; + + var $activeDashboard = $activeEntry.closest(dashboardLoc).toggleClass(activeCls); + var $activeGroup = $activeEntry.find( + 'li.nav-header.panel > ul.panel-collapse.in').closest(groupLoc).toggleClass(activeCls); + + function toggleActiveDashboard($dashboard) { + if ($activeDashboard) { + $activeDashboard.toggleClass(activeCls); + } + if ($activeDashboard === $dashboard) { + $activeDashboard = null; + } else { + $activeDashboard = $dashboard.toggleClass(activeCls); + toggleActiveGroup($activeDashboard.find(groupLoc + ':eq(0)')); + } + } + + function toggleActiveGroup($group) { + if ($group.length) { + if ($activeGroup) { + $activeGroup.toggleClass(activeCls); + } + if ($activeGroup === $group) { + $activeGroup = null; + } else { + $activeGroup = $group.toggleClass(activeCls); + } + } + } + + $(document).on('click', dashboardLoc, function() { + toggleActiveDashboard($(this)); + }).on('click', groupLoc, function(event) { + toggleActiveGroup($(this)); + // prevent the event from toggling an active dashboard + event.stopPropagation(); + }); + +}); diff --git a/openstack_dashboard/templates/horizon/_scripts.html b/openstack_dashboard/templates/horizon/_scripts.html index 7eab545702..2152af3ec1 100644 --- a/openstack_dashboard/templates/horizon/_scripts.html +++ b/openstack_dashboard/templates/horizon/_scripts.html @@ -37,6 +37,7 @@ + diff --git a/openstack_dashboard/test/integration_tests/horizon.conf b/openstack_dashboard/test/integration_tests/horizon.conf index 5a125cb341..79894a2b85 100644 --- a/openstack_dashboard/test/integration_tests/horizon.conf +++ b/openstack_dashboard/test/integration_tests/horizon.conf @@ -4,10 +4,10 @@ [dashboard] # Where the dashboard can be found (string value) -dashboard_url=http://localhost/ +dashboard_url=http://localhost/dashboard/ # Login page for the dashboard (string value) -login_url=http://localhost/auth/login/ +login_url=http://localhost/dashboard/auth/login/ # Dashboard help page url (string value) help_url=http://docs.openstack.org/ @@ -50,7 +50,7 @@ admin_password=secretadmin # Whether is Sahara expected to be available (boolean # value) -sahara=True +sahara=False [scenario] # ssh username for image file (string value) diff --git a/openstack_dashboard/test/integration_tests/regions/bars.py b/openstack_dashboard/test/integration_tests/regions/bars.py index ccd627dd28..4bde621e35 100644 --- a/openstack_dashboard/test/integration_tests/regions/bars.py +++ b/openstack_dashboard/test/integration_tests/regions/bars.py @@ -17,11 +17,12 @@ from openstack_dashboard.test.integration_tests.regions import menus class TopBarRegion(baseregion.BaseRegion): - _user_dropdown_menu_locator = (by.By.ID, 'profile_editor_switcher') + _user_dropdown_menu_locator = (by.By.CSS_SELECTOR, + '.nav.navbar-nav.navbar-right li.dropdown') _openstack_brand_locator = (by.By.CSS_SELECTOR, 'a[href*="/home/"]') _user_dropdown_project_locator = (by.By.CSS_SELECTOR, - 'div.dropdown.context-selection') + 'li.dropdown.context-selection') @property def user(self): diff --git a/openstack_dashboard/test/integration_tests/regions/menus.py b/openstack_dashboard/test/integration_tests/regions/menus.py index 7b76101594..8e29320ba7 100644 --- a/openstack_dashboard/test/integration_tests/regions/menus.py +++ b/openstack_dashboard/test/integration_tests/regions/menus.py @@ -35,12 +35,20 @@ class NavigationAccordionRegion(baseregion.BaseRegion): def project_bar(self): return self._get_element(*self._project_bar_locator) - _first_level_item_selected_locator = (by.By.CSS_SELECTOR, 'dt.active') - _second_level_item_selected_locator = (by.By.CSS_SELECTOR, 'h4.active') + _first_level_item_selected_locator = ( + by.By.CSS_SELECTOR, 'li.openstack-dashboard.selenium-active > a') + _second_level_item_selected_locator = ( + by.By.CSS_SELECTOR, 'li.nav-header.selenium-active > a') - _first_level_item_xpath_template = '//dt[contains(text(),\'%s\')]' - _second_level_item_xpath_template = '//h4[contains(text(),\'%s\')]' - _third_level_item_xpath_template = '//li/a[text()=\'%s\']' + _first_level_item_xpath_template = ( + "//li[contains(concat('', @class, ''), 'openstack-dashboard') " + "and contains(., '%s')]/a") + _second_level_item_xpath_template = ( + "//li[contains(concat('', @class, ''), 'nav-header') " + "and contains(., '%s')]/a") + _third_level_item_xpath_template = ( + "//li[contains(concat('', @class, ''), 'openstack-panel') and " + "contains(., '%s')]/a") def _get_first_level_item_locator(self, text): return (by.By.XPATH, diff --git a/openstack_dashboard/test/integration_tests/tests/test_floatingip.py b/openstack_dashboard/test/integration_tests/tests/test_floatingip.py index b19e5ef356..4591a653b7 100644 --- a/openstack_dashboard/test/integration_tests/tests/test_floatingip.py +++ b/openstack_dashboard/test/integration_tests/tests/test_floatingip.py @@ -14,10 +14,8 @@ # under the License. from openstack_dashboard.test.integration_tests import helpers -from openstack_dashboard.test.integration_tests.tests import decorators -@decorators.skip_because(bugs=["1467950"]) class TestFloatingip(helpers.TestCase): """Checks that the user is able to allocate/release floatingip.""" diff --git a/openstack_dashboard/test/integration_tests/tests/test_keypair.py b/openstack_dashboard/test/integration_tests/tests/test_keypair.py index a4ada35a67..45783b19e9 100644 --- a/openstack_dashboard/test/integration_tests/tests/test_keypair.py +++ b/openstack_dashboard/test/integration_tests/tests/test_keypair.py @@ -14,10 +14,8 @@ # under the License. from openstack_dashboard.test.integration_tests import helpers -from openstack_dashboard.test.integration_tests.tests import decorators -@decorators.skip_because(bugs=["1467950"]) class TestKeypair(helpers.TestCase): """Checks that the user is able to create/delete keypair.""" KEYPAIR_NAME = helpers.gen_random_resource_name("keypair") diff --git a/openstack_dashboard/test/integration_tests/tests/test_user_create_delete.py b/openstack_dashboard/test/integration_tests/tests/test_user_create_delete.py index 7f1c634173..9ae585ea81 100644 --- a/openstack_dashboard/test/integration_tests/tests/test_user_create_delete.py +++ b/openstack_dashboard/test/integration_tests/tests/test_user_create_delete.py @@ -11,10 +11,8 @@ # under the License. from openstack_dashboard.test.integration_tests import helpers -from openstack_dashboard.test.integration_tests.tests import decorators -@decorators.skip_because(bugs=["1467950"]) class TestUser(helpers.AdminTestCase): USER_NAME = helpers.gen_random_resource_name("user")