Merge "Improve Router integration tests coverage"
This commit is contained in:
commit
aba6d1f0da
@ -0,0 +1,38 @@
|
||||
# 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
|
||||
|
||||
|
||||
class NetworkOverviewPage(basepage.BaseNavigationPage):
|
||||
|
||||
DEFAULT_NETWORK_NAME = 'public'
|
||||
|
||||
_network_dd_name_locator = (by.By.CSS_SELECTOR,
|
||||
'dt[title*="Name"]+dd')
|
||||
|
||||
_network_dd_status_locator = (by.By.CSS_SELECTOR,
|
||||
'dt[title*="Status"]+dd')
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
super(NetworkOverviewPage, self).__init__(driver, conf)
|
||||
self._page_title = 'Network Details'
|
||||
|
||||
def is_network_name_present(self, network_name=DEFAULT_NETWORK_NAME):
|
||||
dd_text = self._get_element(*self._network_dd_name_locator).text
|
||||
return dd_text == network_name
|
||||
|
||||
def is_network_status(self, status):
|
||||
dd_text = self._get_element(*self._network_dd_status_locator).text
|
||||
return dd_text == status
|
@ -0,0 +1,101 @@
|
||||
# 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 InterfacesTable(tables.TableRegion):
|
||||
name = "interfaces"
|
||||
CREATE_INTERFACE_FORM_FIELDS = ("subnet_id", "ip_address")
|
||||
|
||||
@tables.bind_table_action('create')
|
||||
def create_interface(self, create_button):
|
||||
create_button.click()
|
||||
return forms.FormRegion(
|
||||
self.driver,
|
||||
self.conf,
|
||||
field_mappings=self.CREATE_INTERFACE_FORM_FIELDS
|
||||
)
|
||||
|
||||
@tables.bind_table_action('delete')
|
||||
def delete_interface(self, delete_button):
|
||||
delete_button.click()
|
||||
return forms.BaseFormRegion(self.driver, self.conf)
|
||||
|
||||
@tables.bind_row_action('delete')
|
||||
def delete_interface_by_row_action(self, delete_button, row):
|
||||
delete_button.click()
|
||||
return forms.BaseFormRegion(self.driver, self.conf)
|
||||
|
||||
|
||||
class RouterInterfacesPage(basepage.BaseNavigationPage):
|
||||
|
||||
INTERFACES_TABLE_STATUS_COLUMN = 'status'
|
||||
INTERFACES_TABLE_NAME_COLUMN = 'name'
|
||||
DEFAULT_IPv4_ADDRESS = '10.1.0.10'
|
||||
DEFAULT_SUBNET = 'private: 10.1.0.0/20 (private-subnet)'
|
||||
|
||||
_breadcrumb_routers_locator = (by.By.CSS_SELECTOR,
|
||||
'ol.breadcrumb>li>' +
|
||||
'a[href*="/dashboard/project/routers"]')
|
||||
|
||||
def __init__(self, driver, conf, router_name):
|
||||
super(RouterInterfacesPage, self).__init__(driver, conf)
|
||||
self._page_title = router_name
|
||||
|
||||
def _get_row_with_interface_name(self, name):
|
||||
return self.interfaces_table.get_row(
|
||||
self.INTERFACES_TABLE_NAME_COLUMN, name)
|
||||
|
||||
@property
|
||||
def interfaces_table(self):
|
||||
return InterfacesTable(self.driver, self.conf)
|
||||
|
||||
@property
|
||||
def interfaces_names(self):
|
||||
return map(lambda row: row.cells[self.
|
||||
INTERFACES_TABLE_NAME_COLUMN].text,
|
||||
self.interfaces_table.rows)
|
||||
|
||||
def switch_to_routers_page(self):
|
||||
self._get_element(*self._breadcrumb_routers_locator).click()
|
||||
|
||||
def create_interface(self):
|
||||
interface_form = self.interfaces_table.create_interface()
|
||||
interface_form.subnet_id.text = self.DEFAULT_SUBNET
|
||||
interface_form.ip_address.text = self.DEFAULT_IPv4_ADDRESS
|
||||
interface_form.submit()
|
||||
|
||||
def delete_interface(self, interface_name):
|
||||
row = self._get_row_with_interface_name(interface_name)
|
||||
row.mark()
|
||||
confirm_delete_interface_form = self.interfaces_table.\
|
||||
delete_interface()
|
||||
confirm_delete_interface_form.submit()
|
||||
|
||||
def delete_interface_by_row_action(self, interface_name):
|
||||
row = self._get_row_with_interface_name(interface_name)
|
||||
confirm_delete_interface = self.interfaces_table.\
|
||||
delete_interface_by_row_action(row)
|
||||
confirm_delete_interface.submit()
|
||||
|
||||
def is_interface_present(self, interface_name):
|
||||
return bool(self._get_row_with_interface_name(interface_name))
|
||||
|
||||
def is_interface_status(self, interface_name, status):
|
||||
row = self._get_row_with_interface_name(interface_name)
|
||||
return row.cells[self.INTERFACES_TABLE_STATUS_COLUMN].text == status
|
@ -0,0 +1,42 @@
|
||||
# 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.project.network\
|
||||
.networkoverviewpage import NetworkOverviewPage
|
||||
|
||||
|
||||
class RouterOverviewPage(basepage.BaseNavigationPage):
|
||||
|
||||
_network_link_locator = (by.By.CSS_SELECTOR,
|
||||
'hr+dl.dl-horizontal>dt:nth-child(3)+dd>a')
|
||||
|
||||
def __init__(self, driver, conf, router_name):
|
||||
super(RouterOverviewPage, self).__init__(driver, conf)
|
||||
self._page_title = router_name
|
||||
|
||||
def is_router_name_present(self, router_name):
|
||||
dd_text = self._get_element(by.By.XPATH,
|
||||
"//dd[.='{0}']".format(router_name)).text
|
||||
return dd_text == router_name
|
||||
|
||||
def is_router_status(self, status):
|
||||
dd_text = self._get_element(by.By.XPATH,
|
||||
"//dd[.='{0}']".format(status)).text
|
||||
return dd_text == status
|
||||
|
||||
def go_to_router_network(self):
|
||||
self._get_element(*self._network_link_locator).click()
|
||||
return NetworkOverviewPage(self.driver, self.conf)
|
@ -10,9 +10,16 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from selenium.common import exceptions
|
||||
|
||||
from selenium.webdriver.common import by
|
||||
|
||||
from openstack_dashboard.test.integration_tests.pages import basepage
|
||||
from openstack_dashboard.test.integration_tests.pages.project.network.\
|
||||
routerinterfacespage import RouterInterfacesPage
|
||||
from openstack_dashboard.test.integration_tests.pages.project.network\
|
||||
.routeroverviewpage import RouterOverviewPage
|
||||
from openstack_dashboard.test.integration_tests.regions import forms
|
||||
from openstack_dashboard.test.integration_tests.regions import tables
|
||||
|
||||
@ -55,6 +62,9 @@ class RoutersPage(basepage.BaseNavigationPage):
|
||||
ROUTERS_TABLE_STATUS_COLUMN = 'status'
|
||||
ROUTERS_TABLE_NETWORK_COLUMN = 'ext_net'
|
||||
|
||||
_interfaces_tab_locator = (by.By.CSS_SELECTOR,
|
||||
'a[href*="tab=router_details__interfaces"]')
|
||||
|
||||
def __init__(self, driver, conf):
|
||||
super(RoutersPage, self).__init__(driver, conf)
|
||||
self._page_title = "Routers"
|
||||
@ -129,3 +139,12 @@ class RoutersPage(basepage.BaseNavigationPage):
|
||||
except exceptions.TimeoutException:
|
||||
return False
|
||||
return True
|
||||
|
||||
def go_to_interfaces_page(self, name):
|
||||
self._get_element(by.By.LINK_TEXT, name).click()
|
||||
self._get_element(*self._interfaces_tab_locator).click()
|
||||
return RouterInterfacesPage(self.driver, self.conf, name)
|
||||
|
||||
def go_to_overview_page(self, name):
|
||||
self._get_element(by.By.LINK_TEXT, name).click()
|
||||
return RouterOverviewPage(self.driver, self.conf, name)
|
||||
|
@ -20,14 +20,12 @@ from openstack_dashboard.test.integration_tests.regions import messages
|
||||
class TestRouters(helpers.TestCase):
|
||||
ROUTER_NAME = helpers.gen_random_resource_name("router")
|
||||
|
||||
def test_router_create(self):
|
||||
"""tests the router creation and deletion functionalities:
|
||||
* creates a new router for public network
|
||||
* verifies the router appears in the routers table as active
|
||||
* deletes the newly created router
|
||||
* verifies the router does not appear in the table after deletion
|
||||
"""
|
||||
routers_page = self.home_pg.go_to_network_routerspage()
|
||||
@property
|
||||
def routers_page(self):
|
||||
return self.home_pg.go_to_network_routerspage()
|
||||
|
||||
def _create_router(self):
|
||||
routers_page = self.routers_page
|
||||
|
||||
routers_page.create_router(self.ROUTER_NAME)
|
||||
self.assertTrue(
|
||||
@ -36,12 +34,125 @@ class TestRouters(helpers.TestCase):
|
||||
self.assertTrue(routers_page.is_router_present(self.ROUTER_NAME))
|
||||
self.assertTrue(routers_page.is_router_active(self.ROUTER_NAME))
|
||||
|
||||
def _delete_router(self):
|
||||
routers_page = self.routers_page
|
||||
routers_page.delete_router(self.ROUTER_NAME)
|
||||
self.assertTrue(
|
||||
routers_page.find_message_and_dismiss(messages.SUCCESS))
|
||||
self.assertFalse(routers_page.find_message_and_dismiss(messages.ERROR))
|
||||
self.assertFalse(routers_page.is_router_present(self.ROUTER_NAME))
|
||||
|
||||
def test_router_create(self):
|
||||
"""tests the router creation and deletion functionalities:
|
||||
* creates a new router for public network
|
||||
* verifies the router appears in the routers table as active
|
||||
* deletes the newly created router
|
||||
* verifies the router does not appear in the table after deletion
|
||||
"""
|
||||
self._create_router()
|
||||
self._delete_router()
|
||||
|
||||
def _create_interface(self, interfaces_page):
|
||||
interfaces_page.create_interface()
|
||||
interface_name = interfaces_page.interfaces_names[0]
|
||||
self.assertTrue(
|
||||
interfaces_page.find_message_and_dismiss(messages.SUCCESS))
|
||||
self.assertFalse(
|
||||
interfaces_page.find_message_and_dismiss(messages.ERROR))
|
||||
self.assertTrue(interfaces_page.is_interface_present(interface_name))
|
||||
self.assertTrue(interfaces_page.is_interface_status(
|
||||
interface_name, 'Down'))
|
||||
|
||||
def _delete_interface(self, interfaces_page, interface_name):
|
||||
interfaces_page.delete_interface(interface_name)
|
||||
self.assertTrue(
|
||||
interfaces_page.find_message_and_dismiss(messages.SUCCESS))
|
||||
self.assertFalse(
|
||||
interfaces_page.find_message_and_dismiss(messages.ERROR))
|
||||
self.assertFalse(interfaces_page.is_interface_present(interface_name))
|
||||
|
||||
def test_router_add_delete_interface(self):
|
||||
"""Tests the router interface creation and deletion functionalities:
|
||||
* Follows the steps to create a new router
|
||||
* Clicks on the new router name from the routers table
|
||||
* Moves to the Interfaces page/tab
|
||||
* Adds a new Interface for the first subnet id available
|
||||
* Verifies the new interface is in the routers table by checking that
|
||||
the interface is present in the table
|
||||
* Deletes the newly created interface
|
||||
* Verifies the interface is no longer in the interfaces table
|
||||
* Switches to the routers view by clicking on the breadcrumb link
|
||||
* Follows the steps to delete the router
|
||||
"""
|
||||
self._create_router()
|
||||
|
||||
routers_page = self.routers_page
|
||||
|
||||
router_interfaces_page = routers_page. \
|
||||
go_to_interfaces_page(self.ROUTER_NAME)
|
||||
|
||||
self._create_interface(router_interfaces_page)
|
||||
|
||||
interface_name = router_interfaces_page.interfaces_names[0]
|
||||
|
||||
self._delete_interface(router_interfaces_page, interface_name)
|
||||
|
||||
router_interfaces_page.switch_to_routers_page()
|
||||
|
||||
self._delete_router()
|
||||
|
||||
def test_router_delete_interface_by_row(self):
|
||||
"""Tests the router interface creation and deletion by
|
||||
row action functionalities:
|
||||
* Follows the steps to create a new router
|
||||
* Clicks on the new router name from the routers table
|
||||
* Moves to the Interfaces page/tab
|
||||
* Adds a new Interface for the first subnet id available
|
||||
* Verifies the new interface is in the routers table
|
||||
* Deletes the newly created interface by row action
|
||||
* Verifies the interface is no longer in the interfaces table
|
||||
* Switches to the routers view by clicking on the breadcrumb link
|
||||
* Follows the steps to delete the router
|
||||
"""
|
||||
self._create_router()
|
||||
|
||||
routers_page = self.routers_page
|
||||
|
||||
router_interfaces_page = routers_page. \
|
||||
go_to_interfaces_page(self.ROUTER_NAME)
|
||||
|
||||
self._create_interface(router_interfaces_page)
|
||||
|
||||
interface_name = router_interfaces_page.interfaces_names[0]
|
||||
|
||||
router_interfaces_page.delete_interface_by_row_action(interface_name)
|
||||
|
||||
router_interfaces_page.switch_to_routers_page()
|
||||
|
||||
self._delete_router()
|
||||
|
||||
def test_router_overview_data(self):
|
||||
self._create_router()
|
||||
|
||||
routers_page = self.routers_page
|
||||
|
||||
router_overview_page = routers_page.\
|
||||
go_to_overview_page(self.ROUTER_NAME)
|
||||
|
||||
self.assertTrue(router_overview_page.
|
||||
is_router_name_present(self.ROUTER_NAME))
|
||||
self.assertTrue(router_overview_page.is_router_status("Active"))
|
||||
|
||||
network_overview_page = router_overview_page.go_to_router_network()
|
||||
|
||||
# By default the router is created in the 'public' network so the line
|
||||
# below checks that such name is present in the network
|
||||
# details/overview page
|
||||
self.assertTrue(network_overview_page.is_network_name_present())
|
||||
self.assertTrue(network_overview_page.is_network_status("Active"))
|
||||
|
||||
self._delete_router()
|
||||
|
||||
|
||||
class TestAdminRouters(helpers.AdminTestCase):
|
||||
ROUTER_NAME = helpers.gen_random_resource_name("router")
|
||||
|
Loading…
x
Reference in New Issue
Block a user