From 3c5be5106b1f9368b546b170255a945fd2868c3a Mon Sep 17 00:00:00 2001 From: Vlad Okhrimenko Date: Thu, 31 Jul 2014 14:40:32 +0300 Subject: [PATCH] Add integration tests for Identity->Projects page The projects page is based on tnovacik's regions patches. Add tests for create, delete project. Partially implements blueprint: selenium-integration-testing Change-Id: I89ecc3960ec27259eb2e4666119e6a6f682e1511 --- .../pages/identity/projectspage.py | 118 ++++++++++++++++++ .../test/integration_tests/regions/forms.py | 18 +++ .../integration_tests/tests/test_projects.py | 28 +++++ 3 files changed, 164 insertions(+) create mode 100644 openstack_dashboard/test/integration_tests/pages/identity/projectspage.py create mode 100644 openstack_dashboard/test/integration_tests/tests/test_projects.py diff --git a/openstack_dashboard/test/integration_tests/pages/identity/projectspage.py b/openstack_dashboard/test/integration_tests/pages/identity/projectspage.py new file mode 100644 index 0000000000..6180d73af2 --- /dev/null +++ b/openstack_dashboard/test/integration_tests/pages/identity/projectspage.py @@ -0,0 +1,118 @@ +# 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.regions import forms +from openstack_dashboard.test.integration_tests.regions import tables + + +class ProjectsPage(basepage.BaseNavigationPage): + + _projects_table_locator = (by.By.CSS_SELECTOR, 'table#tenants') + + _create_project_cancel_button_locator = ( + by.By.CSS_SELECTOR, + 'a.btn.btn-default.secondary.cancel.close') + + _delete_project_submit_button_locator = ( + by.By.CSS_SELECTOR, + 'a.btn.btn-primary') + + _modal_locator = ( + by.By.CSS_SELECTOR, + 'div.modal-backdrop') + + DEFAULT_ENABLED = True + PROJECTS_TABLE_NAME_COLUMN_INDEX = 0 + PROJECTS_TABLE_ACTIONS = ("create_project", "delete_projects") + PROJECTS_TABLE_ROW_ACTIONS = { + tables.ComplexActionRowRegion.PRIMARY_ACTION: "manage_members", + tables.ComplexActionRowRegion.SECONDARY_ACTIONS: ( + "edit_project", + "view_usage", + "modify_quotas", + "delete_project", + "set_as_active_project" + ) + } + + CREATE_PROJECT_FORM_FIELDS = (("name", "description", "enabled"),) + + def __init__(self, driver, conf): + super(ProjectsPage, self).__init__(driver, conf) + self._page_title = "Projects" + + @property + def projects_table(self): + src_elem = self._get_element(*self._projects_table_locator) + return tables.ComplexActionTableRegion(self.driver, + self.conf, src_elem, + self.PROJECTS_TABLE_ACTIONS, + self.PROJECTS_TABLE_ROW_ACTIONS + ) + + @property + def create_project_form(self): + return forms.TabbedFormRegion(self.driver, self.conf, None, + self.CREATE_PROJECT_FORM_FIELDS) + + @property + def create_project_cancel_button(self): + return self._get_element( + *self._create_project_cancel_button_locator) + + @property + def delete_project_submit_button(self): + return self._get_element( + *self._delete_project_submit_button_locator) + + def _get_row_with_project_name(self, name): + return self.projects_table.get_row( + self.PROJECTS_TABLE_NAME_COLUMN_INDEX, name) + + def _cancel_popup(self): + self.create_project_cancel_button.click() + + def switch_project_tab(self, tab_name): + if tab_name == "information": + self.create_project_form.tabs.switch_to(0) + if tab_name == "members": + self.create_project_form.tabs.switch_to(1) + if tab_name == "quota": + self.create_project_form.tabs.switch_to(2) + + def create_project(self, project_name, description=None, + is_enabled=DEFAULT_ENABLED): + self.projects_table.create_project.click() + self.create_project_form.name.text = project_name + if description is not None: + self.create_project_form.description.text = description + if not is_enabled: + self.create_project_form.enabled.unmark() + self.create_project_form.submit.click() + self._wait_till_spinner_disappears() + + def delete_project(self, project_name): + row = self._get_row_with_project_name(project_name) + row.mark() + self.projects_table.delete_projects.click() + self.delete_project_submit_button.click() + + def is_project_present(self, project_name): + return bool(self._get_row_with_project_name(project_name)) + + def delete_from_dropdown_menu(self, project_name): + row = self._get_row_with_project_name(project_name) + row.delete_project.click() + self.delete_project_submit_button.click() diff --git a/openstack_dashboard/test/integration_tests/regions/forms.py b/openstack_dashboard/test/integration_tests/regions/forms.py index 5c215f1450..80925ee03d 100644 --- a/openstack_dashboard/test/integration_tests/regions/forms.py +++ b/openstack_dashboard/test/integration_tests/regions/forms.py @@ -90,6 +90,24 @@ class CheckBoxFormFieldRegion(BaseFormFieldRegion): self.element.click() +class ProjectPageCheckBoxFormFieldRegion(BaseFormFieldRegion): + """Checkbox field for Project-page.""" + + _element_locator = (by.By.CSS_SELECTOR, + 'div > input[type=checkbox]') + + def is_marked(self): + return self.element.is_selected() + + def mark(self): + if not self.is_marked(): + self.element.click() + + def unmark(self): + if self.is_marked(): + self.element.click() + + class ChooseFileFormFieldRegion(BaseFormFieldRegion): """Choose file field.""" diff --git a/openstack_dashboard/test/integration_tests/tests/test_projects.py b/openstack_dashboard/test/integration_tests/tests/test_projects.py new file mode 100644 index 0000000000..90ff70a0e6 --- /dev/null +++ b/openstack_dashboard/test/integration_tests/tests/test_projects.py @@ -0,0 +1,28 @@ +# 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 + + +PROJECT_NAME = helpers.gen_random_resource_name("project") + + +class TestCreateDeleteProject(helpers.AdminTestCase): + + def setUp(self): + super(TestCreateDeleteProject, self).setUp() + self.projects_page = self.home_pg.go_to_identity_projectspage() + + def test_create_delete_project(self): + self.projects_page.create_project(PROJECT_NAME) + self.assertTrue(self.projects_page.is_project_present(PROJECT_NAME)) + self.projects_page.delete_project(PROJECT_NAME) + self.assertFalse(self.projects_page.is_project_present(PROJECT_NAME))