Settings page ChangePassword page and their tests

Two new pages added: Settings page and ChangePassword page.
To test their functionality I wrote two tests:
1. test_user_settings_change
 * changes the system's language
 * changes the timezone
 * changes the number of items per page (page size)
2. test_password_change:
   changes the password, verifies it was indeed changed and
   resets to default password.

To allow the above I've made few changes in other places:
* projectpage - added the go_to_settings_page method.
* helpers - added Selenium's implicit wait for self.driver
  in order to use page_timeout for pages that don't load
  instantly.

https://wiki.openstack.org/wiki/Horizon/Testing/UI

Partially implements blueprint: selenium-integration-testing

Change-Id: I24e01cd13d4a63ffd82505e4fd9cc95ba887e882
This commit is contained in:
Daniel Korn 2014-05-25 13:24:14 +03:00
parent e632cd59c1
commit 2a27c7f4e6
7 changed files with 276 additions and 2 deletions

View File

@ -32,6 +32,7 @@ class BaseTestCase(testtools.TestCase):
# Start the Selenium webdriver and setup configuration.
self.driver = selenium.webdriver.Firefox()
self.conf = config.get_config()
self.driver.implicitly_wait(self.conf.dashboard.page_timeout)
else:
msg = "The INTEGRATION_TESTS env variable is not set."
raise self.skipException(msg)

View File

@ -0,0 +1,70 @@
# 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.
from selenium.webdriver.common import by
from openstack_dashboard.test.integration_tests.pages import basepage
from openstack_dashboard.test.integration_tests.pages import pageobject
class ChangePasswordPage(basepage.BasePage):
@property
def modal(self):
return ChangePasswordPage.ChangePasswordModal(self.driver,
self.conf)
def change_password(self, current, new):
self.fill_field_element(
current, self.modal.current_password)
self.fill_field_element(
new, self.modal.new_password)
self.fill_field_element(
new, self.modal.confirm_new_password)
self.modal.click_on_change_button()
def reset_to_default_password(self, current):
if self.topbar.user.text == self.conf.identity.admin_username:
return self.change_password(current,
self.conf.identity.admin_password)
else:
return self.change_password(current,
self.conf.identity.password)
class ChangePasswordModal(pageobject.PageObject):
_current_password_locator = (by.By.CSS_SELECTOR,
'input#id_current_password')
_new_password_locator = (by.By.CSS_SELECTOR,
'input#id_new_password')
_confirm_new_password_locator = (by.By.CSS_SELECTOR,
'input#id_confirm_password')
_change_submit_button_locator = (by.By.CSS_SELECTOR,
'div.modal-footer button.btn')
@property
def current_password(self):
return self.get_element(*self._current_password_locator)
@property
def new_password(self):
return self.get_element(*self._new_password_locator)
@property
def confirm_new_password(self):
return self.get_element(*self._confirm_new_password_locator)
@property
def change_button(self):
return self.get_element(*self._change_submit_button_locator)
def click_on_change_button(self):
self.change_button.click()

View File

@ -63,8 +63,8 @@ class PageObject(object):
def return_to_previous_page(self):
self.driver.back()
def get_element(self, *element):
return self.driver.find_element(*element)
def get_element(self, *locator):
return self.driver.find_element(*locator)
def fill_field_element(self, data, field_element):
field_element.clear()

View File

@ -11,9 +11,15 @@
# under the License.
from openstack_dashboard.test.integration_tests.pages import basepage
from openstack_dashboard.test.integration_tests.pages import settingspage
class ProjectPage(basepage.BasePage):
def __init__(self, driver, conf):
super(ProjectPage, self).__init__(driver, conf)
self._page_title = 'Instance Overview'
def go_to_settings_page(self):
self.topbar.user_dropdown_menu.click()
self.topbar.settings_link.click()
return settingspage.SettingsPage(self.driver, self.conf)

View File

@ -0,0 +1,99 @@
# 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.
from selenium.webdriver.common import by
from openstack_dashboard.test.integration_tests.pages import basepage
from openstack_dashboard.test.integration_tests.pages import changepasswordpage
from openstack_dashboard.test.integration_tests.pages import pageobject
class SettingsPage(basepage.BasePage):
DEFAULT_LANGUAGE = "en"
DEFAULT_TIMEZONE = "UTC"
DEFAULT_PAGESIZE = "20"
DEFAULT_SETTINGS = {
"language": DEFAULT_LANGUAGE,
"timezone": DEFAULT_TIMEZONE,
"pagesize": DEFAULT_PAGESIZE
}
_change_password_tab_locator = (by.By.CSS_SELECTOR,
'a[href*="/settings/password/"]')
def __init__(self, driver, conf):
super(SettingsPage, self).__init__(driver, conf)
self._page_title = "User Settings"
@property
def modal(self):
return SettingsPage.UserSettingsModal(self.driver, self.conf)
@property
def changepassword(self):
return changepasswordpage.ChangePasswordPage(self.driver, self.conf)
@property
def change_password_tab(self):
return self.get_element(*self._change_password_tab_locator)
def change_language(self, lang=DEFAULT_LANGUAGE):
self.select_dropdown_by_value(lang,
self.modal.language_selection)
self.modal.click_on_save_button()
def change_timezone(self, timezone=DEFAULT_TIMEZONE):
self.select_dropdown_by_value(timezone,
self.modal.timezone_selection)
self.modal.click_on_save_button()
def change_pagesize(self, size=DEFAULT_PAGESIZE):
self.fill_field_element(size, self.modal.pagesize)
self.modal.click_on_save_button()
def return_to_default_settings(self):
self.change_language()
self.change_timezone()
self.change_pagesize()
def go_to_change_password_page(self):
self.change_password_tab.click()
return changepasswordpage.ChangePasswordPage(self.driver, self.conf)
class UserSettingsModal(pageobject.PageObject):
_language_selection_locator = (by.By.CSS_SELECTOR,
'select#id_language')
_timezone_selection_locator = (by.By.CSS_SELECTOR,
'select#id_timezone')
_items_per_page_input_locator = (by.By.CSS_SELECTOR,
'input#id_pagesize')
_save_submit_button_locator = (by.By.CSS_SELECTOR,
'div.modal-footer button.btn')
@property
def language_selection(self):
return self.get_element(*self._language_selection_locator)
@property
def timezone_selection(self):
return self.get_element(*self._timezone_selection_locator)
@property
def pagesize(self):
return self.get_element(*self._items_per_page_input_locator)
@property
def save_button(self):
return self.get_element(*self._save_submit_button_locator)
def click_on_save_button(self):
self.save_button.click()

View File

@ -0,0 +1,45 @@
# 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.
from openstack_dashboard.test.integration_tests import helpers
NEW_PASSWORD = "123"
class TestPasswordChange(helpers.TestCase):
def test_password_change(self):
"""Changes the password, verifies it was indeed changed and resets to
default password.
"""
settings_page = self.home_pg.go_to_settings_page()
passwordchange_page = settings_page.go_to_change_password_page()
try:
passwordchange_page.change_password(self.conf.identity.password,
NEW_PASSWORD)
self.home_pg = self.login_pg.login(
user=self.conf.identity.username, password=NEW_PASSWORD)
self.assertTrue(self.home_pg.is_logged_in,
"Failed to login with new password")
settings_page = self.home_pg.go_to_settings_page()
passwordchange_page = settings_page.go_to_change_password_page()
finally:
passwordchange_page.reset_to_default_password(NEW_PASSWORD)
def tearDown(self):
self.login_pg.login()
self.assertTrue(self.home_pg.is_logged_in,
"Failed to login with default password")
super(TestPasswordChange, self).tearDown()

View File

@ -0,0 +1,53 @@
# 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.
from openstack_dashboard.test.integration_tests import helpers
class TestUserSettings(helpers.TestCase):
def verify_user_settings_change(self, changed_settings):
language = self.settings_page.modal.language_selection.\
get_attribute("value")
timezone = self.settings_page.modal.timezone_selection.\
get_attribute("value")
pagesize = self.settings_page.modal.pagesize.\
get_attribute("value")
user_settings = (("Language", changed_settings["language"], language),
("Timezone", changed_settings["timezone"], timezone),
("Pagesize", changed_settings["pagesize"], pagesize))
for (setting, expected, observed) in user_settings:
self.assertEqual(expected, observed,
"expected %s: %s, instead found: %s"
% (setting, expected, observed))
def test_user_settings_change(self):
"""tests the user's settings options:
* changes the system's language
* changes the timezone
* changes the number of items per page (page size)
* verifies all changes were successfully executed
"""
self.settings_page = self.home_pg.go_to_settings_page()
self.settings_page.change_language("es")
self.settings_page.change_timezone("Asia/Jerusalem")
self.settings_page.change_pagesize("30")
changed_settings = {"language": "es", "timezone": "Asia/Jerusalem",
"pagesize": "30"}
self.verify_user_settings_change(changed_settings)
self.settings_page.return_to_default_settings()
self.verify_user_settings_change(self.settings_page.DEFAULT_SETTINGS)