Make unit testing less reliant on HTML fragments
Some tests check for equality with quite large HTML fragments, when the test is only interested in certain specific things (and not style changes etc). This patch alters some of those tests (specifically ones that were tripping up a dependent patch, but can be expanded) to check the context data of the response, since the actual rendering is tested by horizon's tests. It also adds tests to check context data in 'normal' circumstances so that no test coverage should be lost by this. Change-Id: I09be82058edc923521ffb4c022515845a18b158d Closes-Bug: #1517084
This commit is contained in:
parent
8476319cd0
commit
d76a61346e
@ -25,8 +25,6 @@ from mox3.mox import IsA # noqa
|
||||
import six
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.access_and_security \
|
||||
.floating_ips import tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
@ -214,6 +212,68 @@ class FloatingIpViewTests(test.TestCase):
|
||||
res = self.client.post(INDEX_URL, {"action": action})
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
'floating_ip_pools_list',),
|
||||
api.nova: ('keypair_list',
|
||||
'server_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
api.base: ('is_service_enabled',)})
|
||||
def test_allocate_button_attributes(self):
|
||||
keypairs = self.keypairs.list()
|
||||
floating_ips = self.floating_ips.list()
|
||||
floating_pools = self.pools.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['floating_ips']['available'] = 10
|
||||
sec_groups = self.security_groups.list()
|
||||
|
||||
api.network.floating_ip_supported(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.security_group_list(
|
||||
IsA(http.HttpRequest)).MultipleTimes()\
|
||||
.AndReturn(sec_groups)
|
||||
api.network.floating_ip_pools_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
api.nova.keypair_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(keypairs)
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)).MultipleTimes() \
|
||||
.AndReturn(quota_data)
|
||||
|
||||
api.base.is_service_enabled(
|
||||
IsA(http.HttpRequest),
|
||||
'network').MultipleTimes() \
|
||||
.AndReturn(True)
|
||||
api.base.is_service_enabled(
|
||||
IsA(http.HttpRequest),
|
||||
'ec2').MultipleTimes() \
|
||||
.AndReturn(False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL +
|
||||
"?tab=access_security_tabs__floating_ips_tab")
|
||||
|
||||
allocate_action = self.getAndAssertTableAction(res, 'floating_ips',
|
||||
'allocate')
|
||||
self.assertEqual(set(['ajax-modal']), set(allocate_action.classes))
|
||||
self.assertEqual('Allocate IP To Project',
|
||||
six.text_type(allocate_action.verbose_name))
|
||||
self.assertEqual(None, allocate_action.policy_rules)
|
||||
|
||||
url = 'horizon:project:access_and_security:floating_ips:allocate'
|
||||
self.assertEqual(url, allocate_action.url)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
@ -266,19 +326,12 @@ class FloatingIpViewTests(test.TestCase):
|
||||
res = self.client.get(INDEX_URL +
|
||||
"?tab=access_security_tabs__floating_ips_tab")
|
||||
|
||||
allocate_link = tables.AllocateIP()
|
||||
url = allocate_link.get_link_url()
|
||||
classes = (list(allocate_link.get_default_classes())
|
||||
+ list(allocate_link.classes))
|
||||
link_name = "%s (%s)" % (six.text_type(allocate_link.verbose_name),
|
||||
"Quota exceeded")
|
||||
expected_string = ("<a href='%s' title='%s' class='%s disabled' "
|
||||
"id='floating_ips__action_allocate'>"
|
||||
"<span class='fa fa-link'>"
|
||||
"</span>%s</a>"
|
||||
% (url, link_name, " ".join(classes), link_name))
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The create button is not disabled")
|
||||
allocate_action = self.getAndAssertTableAction(res, 'floating_ips',
|
||||
'allocate')
|
||||
self.assertTrue('disabled' in allocate_action.classes,
|
||||
'The create button should be disabled')
|
||||
self.assertEqual('Allocate IP To Project (Quota exceeded)',
|
||||
six.text_type(allocate_action.verbose_name))
|
||||
|
||||
|
||||
class FloatingIpNeutronViewTests(FloatingIpViewTests):
|
||||
|
@ -27,8 +27,6 @@ from horizon.workflows import views
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.access_and_security \
|
||||
import api_access
|
||||
from openstack_dashboard.dashboards.project.access_and_security \
|
||||
.security_groups import tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
@ -163,6 +161,70 @@ class SecurityGroupTabTests(test.TestCase):
|
||||
def setUp(self):
|
||||
super(SecurityGroupTabTests, self).setUp()
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
'floating_ip_pools_list',),
|
||||
api.nova: ('keypair_list',
|
||||
'server_list',),
|
||||
quotas: ('tenant_quota_usages',),
|
||||
api.base: ('is_service_enabled',)})
|
||||
def test_create_button_attributes(self):
|
||||
keypairs = self.keypairs.list()
|
||||
floating_ips = self.floating_ips.list()
|
||||
floating_pools = self.pools.list()
|
||||
sec_groups = self.security_groups.list()
|
||||
quota_data = self.quota_usages.first()
|
||||
quota_data['security_groups']['available'] = 10
|
||||
|
||||
api.network.floating_ip_supported(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.network.tenant_floating_ip_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_ips)
|
||||
api.network.floating_ip_pools_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(floating_pools)
|
||||
api.network.security_group_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(sec_groups)
|
||||
api.nova.keypair_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(keypairs)
|
||||
api.nova.server_list(
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn([self.servers.list(), False])
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)).MultipleTimes() \
|
||||
.AndReturn(quota_data)
|
||||
|
||||
api.base.is_service_enabled(
|
||||
IsA(http.HttpRequest), 'network').MultipleTimes() \
|
||||
.AndReturn(True)
|
||||
api.base.is_service_enabled(
|
||||
IsA(http.HttpRequest), 'ec2').MultipleTimes() \
|
||||
.AndReturn(False)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(INDEX_URL +
|
||||
"?tab=access_security_tabs__security_groups_tab")
|
||||
|
||||
security_groups = res.context['security_groups_table'].data
|
||||
self.assertItemsEqual(security_groups, self.security_groups.list())
|
||||
|
||||
create_action = self.getAndAssertTableAction(res, 'security_groups',
|
||||
'create')
|
||||
|
||||
self.assertEqual('Create Security Group',
|
||||
six.text_type(create_action.verbose_name))
|
||||
self.assertEqual(None, create_action.policy_rules)
|
||||
self.assertEqual(set(['ajax-modal']), set(create_action.classes))
|
||||
|
||||
url = 'horizon:project:access_and_security:security_groups:create'
|
||||
self.assertEqual(url, create_action.url)
|
||||
|
||||
@test.create_stubs({api.network: ('floating_ip_supported',
|
||||
'tenant_floating_ip_list',
|
||||
'security_group_list',
|
||||
@ -217,18 +279,10 @@ class SecurityGroupTabTests(test.TestCase):
|
||||
security_groups = res.context['security_groups_table'].data
|
||||
self.assertItemsEqual(security_groups, self.security_groups.list())
|
||||
|
||||
create_link = tables.CreateGroup()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (six.text_type(create_link.verbose_name),
|
||||
"Quota exceeded")
|
||||
expected_string = "<a href='%s' title='%s' class='%s disabled' "\
|
||||
"id='security_groups__action_create'>" \
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, link_name, " ".join(classes), link_name)
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The create button is not disabled")
|
||||
create_action = self.getAndAssertTableAction(res, 'security_groups',
|
||||
'create')
|
||||
self.assertTrue('disabled' in create_action.classes,
|
||||
'The create button should be disabled')
|
||||
|
||||
def test_create_button_disabled_when_quota_exceeded_neutron_disabled(self):
|
||||
self._test_create_button_disabled_when_quota_exceeded(False)
|
||||
|
@ -28,7 +28,6 @@ from django.core.urlresolvers import reverse
|
||||
from django.forms import widgets
|
||||
from django import http
|
||||
import django.test
|
||||
from django.utils import encoding
|
||||
from django.utils.http import urlencode
|
||||
from mox3.mox import IgnoreArg # noqa
|
||||
from mox3.mox import IsA # noqa
|
||||
@ -3587,6 +3586,54 @@ class InstanceTests(helpers.TestCase):
|
||||
self.test_launch_form_instance_non_int_volume_size(
|
||||
test_with_profile=True)
|
||||
|
||||
@helpers.create_stubs({
|
||||
api.nova: ('flavor_list', 'server_list', 'tenant_absolute_limits',
|
||||
'extension_supported',),
|
||||
api.glance: ('image_list_detailed',),
|
||||
api.network: ('floating_ip_simple_associate_supported',
|
||||
'floating_ip_supported',
|
||||
'servers_update_addresses',),
|
||||
})
|
||||
def test_launch_button_attributes(self):
|
||||
servers = self.servers.list()
|
||||
limits = self.limits['absolute']
|
||||
limits['totalInstancesUsed'] = 0
|
||||
|
||||
api.nova.extension_supported('AdminActions',
|
||||
IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.glance.image_list_detailed(IgnoreArg()) \
|
||||
.AndReturn((self.images.list(), False, False))
|
||||
search_opts = {'marker': None, 'paginate': True}
|
||||
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
|
||||
.AndReturn([servers, False])
|
||||
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
|
||||
.MultipleTimes().AndReturn(limits)
|
||||
api.network.floating_ip_supported(IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.network.floating_ip_simple_associate_supported(
|
||||
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
tables.LaunchLink()
|
||||
res = self.client.get(INDEX_URL)
|
||||
|
||||
launch_action = self.getAndAssertTableAction(res, 'instances',
|
||||
'launch')
|
||||
|
||||
self.assertEqual(set(['ajax-modal', 'ajax-update', 'btn-launch']),
|
||||
set(launch_action.classes))
|
||||
self.assertEqual('Launch Instance', launch_action.verbose_name)
|
||||
self.assertEqual('horizon:project:instances:launch', launch_action.url)
|
||||
self.assertEqual((('compute', 'compute:create'),),
|
||||
launch_action.policy_rules)
|
||||
|
||||
@helpers.create_stubs({
|
||||
api.nova: ('flavor_list', 'server_list', 'tenant_absolute_limits',
|
||||
'extension_supported',),
|
||||
@ -3622,27 +3669,16 @@ class InstanceTests(helpers.TestCase):
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
launch = tables.LaunchLink()
|
||||
url = launch.get_link_url()
|
||||
classes = list(launch.get_default_classes()) + list(launch.classes)
|
||||
link_name = "%s (%s)" % (six.text_type(launch.verbose_name),
|
||||
"Quota exceeded")
|
||||
|
||||
tables.LaunchLink()
|
||||
res = self.client.get(INDEX_URL)
|
||||
if django.VERSION < (1, 8, 0):
|
||||
resp_charset = res._charset
|
||||
else:
|
||||
resp_charset = res.charset
|
||||
expected_string = encoding.smart_str(u'''
|
||||
<a href="%s" title="%s" class="%s disabled"
|
||||
data-update-url=
|
||||
"/project/instances/?action=launch&table=instances"
|
||||
id="instances__action_launch">
|
||||
<span class="fa fa-cloud-upload"></span>%s</a>
|
||||
''' % (url, link_name, " ".join(classes), link_name), resp_charset)
|
||||
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The launch button is not disabled")
|
||||
launch_action = self.getAndAssertTableAction(
|
||||
res, 'instances', 'launch')
|
||||
|
||||
self.assertTrue('disabled' in launch_action.classes,
|
||||
'The launch button should be disabled')
|
||||
self.assertEqual('Launch Instance (Quota exceeded)',
|
||||
six.text_type(launch_action.verbose_name))
|
||||
|
||||
@helpers.create_stubs({api.glance: ('image_list_detailed',),
|
||||
api.neutron: ('network_list',),
|
||||
|
@ -19,10 +19,9 @@ from django.utils.html import escape
|
||||
from horizon.workflows import views
|
||||
|
||||
from mox3.mox import IsA # noqa
|
||||
import six
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.networks.subnets import tables\
|
||||
as subnets_tables
|
||||
from openstack_dashboard.dashboards.project.networks import tables\
|
||||
as networks_tables
|
||||
from openstack_dashboard.dashboards.project.networks import workflows
|
||||
@ -2013,7 +2012,8 @@ class NetworkSubnetTests(test.TestCase):
|
||||
class NetworkViewTests(test.TestCase, NetworkStubMixin):
|
||||
|
||||
def _test_create_button_shown_when_quota_disabled(
|
||||
self, expected_string):
|
||||
self,
|
||||
find_button_fn):
|
||||
# if quota_data doesnt contain a networks|subnets|routers key or
|
||||
# these keys are empty dicts, its disabled
|
||||
quota_data = self.neutron_quota_usages.first()
|
||||
@ -2033,11 +2033,14 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
|
||||
|
||||
networks = res.context['networks_table'].data
|
||||
self.assertItemsEqual(networks, self.networks.list())
|
||||
self.assertContains(res, expected_string, True, html=True,
|
||||
msg_prefix="The enabled create button not shown")
|
||||
|
||||
button = find_button_fn(res)
|
||||
self.assertFalse('disabled' in button.classes,
|
||||
"The create button should not be disabled")
|
||||
return button
|
||||
|
||||
def _test_create_button_disabled_when_quota_exceeded(
|
||||
self, expected_string, network_quota=5, subnet_quota=5):
|
||||
self, find_button_fn, network_quota=5, subnet_quota=5, ):
|
||||
|
||||
quota_data = self.neutron_quota_usages.first()
|
||||
|
||||
@ -2056,69 +2059,55 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
|
||||
|
||||
networks = res.context['networks_table'].data
|
||||
self.assertItemsEqual(networks, self.networks.list())
|
||||
self.assertContains(res, expected_string, True, html=True,
|
||||
msg_prefix="The create button is not disabled")
|
||||
|
||||
button = find_button_fn(res)
|
||||
self.assertTrue('disabled' in button.classes,
|
||||
"The create button should be disabled")
|
||||
return button
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_list',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_network_create_button_disabled_when_quota_exceeded_index(self):
|
||||
create_link = networks_tables.CreateNetwork()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (create_link.verbose_name, "Quota exceeded")
|
||||
expected_string = "<a href='%s' title='%s' class='%s disabled' "\
|
||||
"id='networks__action_create'>" \
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, link_name, " ".join(classes), link_name)
|
||||
self._test_create_button_disabled_when_quota_exceeded(expected_string,
|
||||
network_quota=0
|
||||
)
|
||||
networks_tables.CreateNetwork()
|
||||
|
||||
def _find_net_button(res):
|
||||
return self.getAndAssertTableAction(res, 'networks', 'create')
|
||||
self._test_create_button_disabled_when_quota_exceeded(_find_net_button,
|
||||
network_quota=0)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_list',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_subnet_create_button_disabled_when_quota_exceeded_index(self):
|
||||
network_id = self.networks.first().id
|
||||
create_link = networks_tables.CreateSubnet()
|
||||
url = reverse(create_link.get_link_url(), args=[network_id])
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (create_link.verbose_name, "Quota exceeded")
|
||||
expected_string = "<a href='%s' class='%s disabled' " \
|
||||
"id='networks__row_%s__action_subnet'>%s</a>" \
|
||||
% (url, " ".join(classes), network_id, link_name)
|
||||
self._test_create_button_disabled_when_quota_exceeded(expected_string,
|
||||
subnet_quota=0
|
||||
)
|
||||
networks_tables.CreateSubnet()
|
||||
|
||||
def _find_subnet_button(res):
|
||||
return self.getAndAssertTableRowAction(res, 'networks',
|
||||
'subnet', network_id)
|
||||
|
||||
self._test_create_button_disabled_when_quota_exceeded(
|
||||
_find_subnet_button, subnet_quota=0)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_list',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_network_create_button_shown_when_quota_disabled_index(self):
|
||||
# if quota_data doesnt contain a networks["available"] key its disabled
|
||||
create_link = networks_tables.CreateNetwork()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
expected_string = "<a href='%s' title='%s' class='%s' "\
|
||||
"id='networks__action_create'>" \
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, create_link.verbose_name, " ".join(classes),
|
||||
create_link.verbose_name)
|
||||
self._test_create_button_shown_when_quota_disabled(expected_string)
|
||||
networks_tables.CreateNetwork()
|
||||
self._test_create_button_shown_when_quota_disabled(
|
||||
lambda res: self.getAndAssertTableAction(res, 'networks', 'create')
|
||||
)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_list',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_subnet_create_button_shown_when_quota_disabled_index(self):
|
||||
# if quota_data doesnt contain a subnets["available"] key, its disabled
|
||||
network_id = self.networks.first().id
|
||||
create_link = networks_tables.CreateSubnet()
|
||||
url = reverse(create_link.get_link_url(), args=[network_id])
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
expected_string = "<a href='%s' class='%s' "\
|
||||
"id='networks__row_%s__action_subnet'>%s</a>" \
|
||||
% (url, " ".join(classes), network_id, create_link.verbose_name)
|
||||
self._test_create_button_shown_when_quota_disabled(expected_string)
|
||||
|
||||
def _find_subnet_button(res):
|
||||
return self.getAndAssertTableRowAction(res, 'networks',
|
||||
'subnet', network_id)
|
||||
|
||||
self._test_create_button_shown_when_quota_disabled(_find_subnet_button)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_get',
|
||||
'subnet_list',
|
||||
@ -2155,17 +2144,65 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
|
||||
subnets = res.context['subnets_table'].data
|
||||
self.assertItemsEqual(subnets, self.subnets.list())
|
||||
|
||||
class FakeTable(object):
|
||||
kwargs = {'network_id': network_id}
|
||||
create_link = subnets_tables.CreateSubnet()
|
||||
create_link.table = FakeTable()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (create_link.verbose_name, "Quota exceeded")
|
||||
expected_string = "<a href='%s' title='%s' class='%s disabled' "\
|
||||
"id='subnets__action_create'>" \
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, link_name, " ".join(classes), link_name)
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The create button is not disabled")
|
||||
create_action = self.getAndAssertTableAction(res, 'subnets', 'create')
|
||||
self.assertTrue('disabled' in create_action.classes,
|
||||
'The create button should be disabled')
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_list',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_create_button_attributes(self):
|
||||
create_action = self._test_create_button_shown_when_quota_disabled(
|
||||
lambda res: self.getAndAssertTableAction(res, 'networks', 'create')
|
||||
)
|
||||
|
||||
self.assertEqual(set(['ajax-modal']), set(create_action.classes))
|
||||
self.assertEqual('horizon:project:networks:create', create_action.url)
|
||||
self.assertEqual('Create Network',
|
||||
six.text_type(create_action.verbose_name))
|
||||
self.assertEqual((('network', 'create_network'),),
|
||||
create_action.policy_rules)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_get',
|
||||
'subnet_list',
|
||||
'port_list',
|
||||
'is_extension_supported',),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_create_subnet_button_attributes(self):
|
||||
network_id = self.networks.first().id
|
||||
quota_data = self.neutron_quota_usages.first()
|
||||
quota_data['subnets']['available'] = 1
|
||||
|
||||
api.neutron.network_get(
|
||||
IsA(http.HttpRequest), network_id)\
|
||||
.MultipleTimes().AndReturn(self.networks.first())
|
||||
api.neutron.subnet_list(
|
||||
IsA(http.HttpRequest), network_id=network_id)\
|
||||
.AndReturn(self.subnets.list())
|
||||
api.neutron.port_list(
|
||||
IsA(http.HttpRequest), network_id=network_id)\
|
||||
.AndReturn([self.ports.first()])
|
||||
api.neutron.is_extension_supported(
|
||||
IsA(http.HttpRequest), 'mac-learning')\
|
||||
.AndReturn(False)
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(quota_data)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(reverse('horizon:project:networks:detail',
|
||||
args=[network_id]))
|
||||
self.assertTemplateUsed(res, 'project/networks/detail.html')
|
||||
|
||||
subnets = res.context['subnets_table'].data
|
||||
self.assertItemsEqual(subnets, self.subnets.list())
|
||||
|
||||
create_action = self.getAndAssertTableAction(res, 'subnets', 'create')
|
||||
|
||||
self.assertEqual(set(['ajax-modal']), set(create_action.classes))
|
||||
self.assertEqual('horizon:project:networks:addsubnet',
|
||||
create_action.url)
|
||||
self.assertEqual('Create Subnet',
|
||||
six.text_type(create_action.verbose_name))
|
||||
self.assertEqual((('network', 'create_subnet'),),
|
||||
create_action.policy_rules)
|
||||
|
@ -23,7 +23,6 @@ import six
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.routers.extensions.routerrules\
|
||||
import rulemanager
|
||||
from openstack_dashboard.dashboards.project.routers import tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
@ -938,18 +937,11 @@ class RouterViewTests(RouterMixin, test.TestCase):
|
||||
routers = res.context['Routers_table'].data
|
||||
self.assertItemsEqual(routers, self.routers.list())
|
||||
|
||||
create_link = tables.CreateRouter()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (six.text_type(create_link.verbose_name),
|
||||
"Quota exceeded")
|
||||
expected_string = "<a href='%s' title='%s' class='%s disabled' "\
|
||||
"id='Routers__action_create'>" \
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, link_name, " ".join(classes), link_name)
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The create button is not disabled")
|
||||
create_action = self.getAndAssertTableAction(res, 'Routers', 'create')
|
||||
self.assertTrue('disabled' in create_action.classes,
|
||||
'Create button is not disabled')
|
||||
self.assertEqual('Create Router (Quota exceeded)',
|
||||
create_action.verbose_name)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_list', 'network_list'),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
@ -973,14 +965,38 @@ class RouterViewTests(RouterMixin, test.TestCase):
|
||||
routers = res.context['Routers_table'].data
|
||||
self.assertItemsEqual(routers, self.routers.list())
|
||||
|
||||
create_link = tables.CreateRouter()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s" % (six.text_type(create_link.verbose_name))
|
||||
expected_string = "<a href='%s' title='%s' class='%s' "\
|
||||
"id='Routers__action_create'>" \
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, link_name, " ".join(classes), link_name)
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The create button is not displayed")
|
||||
create_action = self.getAndAssertTableAction(res, 'Routers', 'create')
|
||||
self.assertFalse('disabled' in create_action.classes,
|
||||
'Create button should not be disabled')
|
||||
self.assertEqual('Create Router',
|
||||
create_action.verbose_name)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_list', 'network_list'),
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_create_button_attributes(self):
|
||||
quota_data = self.neutron_quota_usages.first()
|
||||
quota_data['routers']['available'] = 10
|
||||
api.neutron.router_list(
|
||||
IsA(http.HttpRequest),
|
||||
tenant_id=self.tenant.id,
|
||||
search_opts=None).AndReturn(self.routers.list())
|
||||
quotas.tenant_quota_usages(
|
||||
IsA(http.HttpRequest)) \
|
||||
.MultipleTimes().AndReturn(quota_data)
|
||||
|
||||
self._mock_external_network_list()
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(self.INDEX_URL)
|
||||
self.assertTemplateUsed(res, 'project/routers/index.html')
|
||||
|
||||
routers = res.context['Routers_table'].data
|
||||
self.assertItemsEqual(routers, self.routers.list())
|
||||
|
||||
create_action = self.getAndAssertTableAction(res, 'Routers', 'create')
|
||||
self.assertEqual(set(['ajax-modal']), set(create_action.classes))
|
||||
self.assertEqual('Create Router',
|
||||
six.text_type(create_action.verbose_name))
|
||||
self.assertEqual('horizon:project:routers:create', create_action.url)
|
||||
self.assertEqual((('network', 'create_router'),),
|
||||
create_action.policy_rules)
|
||||
|
@ -15,7 +15,6 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import django
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.forms import widgets
|
||||
@ -24,11 +23,10 @@ from django.test.utils import override_settings
|
||||
|
||||
from mox3.mox import IsA # noqa
|
||||
import six
|
||||
from six import moves
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.api import cinder
|
||||
from openstack_dashboard.dashboards.project.volumes \
|
||||
.volumes import tables
|
||||
from openstack_dashboard.test import helpers as test
|
||||
from openstack_dashboard.usage import quotas
|
||||
|
||||
@ -1021,6 +1019,50 @@ class VolumeViewTests(test.TestCase):
|
||||
server.id)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
def _get_volume_row_action_from_ajax(self, res, action_name, row_id):
|
||||
def _matches_row_id(context_row):
|
||||
return (len(context_row.dicts) > 1 and
|
||||
isinstance(context_row.dicts[1], dict) and
|
||||
context_row.dicts[1].get('row_id', None) == row_id)
|
||||
|
||||
matching = list(moves.filter(lambda r: _matches_row_id(r),
|
||||
res.context))
|
||||
self.assertTrue(len(matching) > 1,
|
||||
"Expected at least one row matching %s" % row_id)
|
||||
row = matching[-1].dicts[1]
|
||||
matching_actions = list(moves.filter(lambda a: a.name == action_name,
|
||||
row['row_actions']))
|
||||
self.assertEqual(1, len(matching_actions),
|
||||
"Expected one row action named '%s'" % action_name)
|
||||
return matching_actions[0]
|
||||
|
||||
@test.create_stubs({cinder: ('tenant_absolute_limits',
|
||||
'volume_get',)})
|
||||
def test_create_snapshot_button_attributes(self):
|
||||
limits = {'maxTotalSnapshots': 2}
|
||||
limits['totalSnapshotsUsed'] = 1
|
||||
volume = self.cinder_volumes.first()
|
||||
|
||||
cinder.volume_get(IsA(http.HttpRequest), volume.id).AndReturn(volume)
|
||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).AndReturn(limits)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res_url = (VOLUME_INDEX_URL +
|
||||
"?action=row_update&table=volumes&obj_id=" + volume.id)
|
||||
|
||||
res = self.client.get(res_url, {},
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
|
||||
snapshot_action = self._get_volume_row_action_from_ajax(
|
||||
res, 'snapshots', volume.id)
|
||||
self.assertEqual('horizon:project:volumes:volumes:create_snapshot',
|
||||
snapshot_action.url)
|
||||
self.assertEqual(set(['ajax-modal']), set(snapshot_action.classes))
|
||||
self.assertEqual('Create Snapshot',
|
||||
six.text_type(snapshot_action.verbose_name))
|
||||
self.assertEqual((('volume', 'volume:create_snapshot'),),
|
||||
snapshot_action.policy_rules)
|
||||
|
||||
@test.create_stubs({cinder: ('tenant_absolute_limits',
|
||||
'volume_get',)})
|
||||
def test_create_snapshot_button_disabled_when_quota_exceeded(self):
|
||||
@ -1032,25 +1074,57 @@ class VolumeViewTests(test.TestCase):
|
||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest)).AndReturn(limits)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
create_link = tables.CreateSnapshot()
|
||||
url = reverse(create_link.get_link_url(), args=[volume.id])
|
||||
res_url = (VOLUME_INDEX_URL +
|
||||
"?action=row_update&table=volumes&obj_id=" + volume.id)
|
||||
|
||||
res = self.client.get(res_url, {},
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
||||
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (six.text_type(create_link.verbose_name),
|
||||
"Quota exceeded")
|
||||
expected_string = "<a href='%s' class=\"%s disabled\" "\
|
||||
"id=\"volumes__row_%s__action_snapshots\">%s</a>" \
|
||||
% (url, " ".join(classes), volume.id, link_name)
|
||||
snapshot_action = self._get_volume_row_action_from_ajax(
|
||||
res, 'snapshots', volume.id)
|
||||
self.assertTrue('disabled' in snapshot_action.classes,
|
||||
'The create snapshot button should be disabled')
|
||||
|
||||
self.assertContains(
|
||||
res, expected_string, html=True,
|
||||
msg_prefix="The create snapshot button is not disabled")
|
||||
@test.create_stubs({cinder: ('tenant_absolute_limits',
|
||||
'volume_list',
|
||||
'volume_snapshot_list',
|
||||
'volume_backup_supported',),
|
||||
api.nova: ('server_list',)})
|
||||
def test_create_button_attributes(self):
|
||||
limits = self.cinder_limits['absolute']
|
||||
limits['maxTotalVolumes'] = 10
|
||||
limits['totalVolumesUsed'] = 1
|
||||
volumes = self.cinder_volumes.list()
|
||||
|
||||
api.cinder.volume_backup_supported(IsA(http.HttpRequest)). \
|
||||
MultipleTimes().AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest), search_opts=None)\
|
||||
.AndReturn(volumes)
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest),
|
||||
search_opts=None).\
|
||||
AndReturn([])
|
||||
api.nova.server_list(IsA(http.HttpRequest), search_opts=None)\
|
||||
.AndReturn([self.servers.list(), False])
|
||||
cinder.tenant_absolute_limits(IsA(http.HttpRequest))\
|
||||
.MultipleTimes().AndReturn(limits)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.get(VOLUME_INDEX_URL)
|
||||
self.assertTemplateUsed(res, 'project/volumes/index.html')
|
||||
|
||||
volumes = res.context['volumes_table'].data
|
||||
self.assertItemsEqual(volumes, self.cinder_volumes.list())
|
||||
|
||||
create_action = self.getAndAssertTableAction(res, 'volumes', 'create')
|
||||
|
||||
self.assertEqual(set(['ajax-modal', 'ajax-update', 'btn-create']),
|
||||
set(create_action.classes))
|
||||
self.assertEqual('Create Volume',
|
||||
six.text_type(create_action.verbose_name))
|
||||
self.assertEqual('horizon:project:volumes:volumes:create',
|
||||
create_action.url)
|
||||
self.assertEqual((('volume', 'volume:create'),),
|
||||
create_action.policy_rules)
|
||||
|
||||
@test.create_stubs({cinder: ('tenant_absolute_limits',
|
||||
'volume_list',
|
||||
@ -1081,19 +1155,9 @@ class VolumeViewTests(test.TestCase):
|
||||
volumes = res.context['volumes_table'].data
|
||||
self.assertItemsEqual(volumes, self.cinder_volumes.list())
|
||||
|
||||
create_link = tables.CreateVolume()
|
||||
url = create_link.get_link_url()
|
||||
classes = (list(create_link.get_default_classes())
|
||||
+ list(create_link.classes))
|
||||
link_name = "%s (%s)" % (six.text_type(create_link.verbose_name),
|
||||
"Quota exceeded")
|
||||
expected_string = "<a href='%s' title='%s' class='%s disabled' "\
|
||||
"id='volumes__action_create' data-update-url=" \
|
||||
"'/project/volumes/?action=create&table=volumes'> "\
|
||||
"<span class='fa fa-plus'></span>%s</a>" \
|
||||
% (url, link_name, " ".join(classes), link_name)
|
||||
self.assertContains(res, expected_string, html=True,
|
||||
msg_prefix="The create button is not disabled")
|
||||
create_action = self.getAndAssertTableAction(res, 'volumes', 'create')
|
||||
self.assertTrue('disabled' in create_action.classes,
|
||||
'The create button should be disabled')
|
||||
|
||||
@test.create_stubs({cinder: ('tenant_absolute_limits',
|
||||
'volume_get',),
|
||||
|
@ -280,6 +280,44 @@ class TestCase(horizon_helpers.TestCase):
|
||||
def assertItemsCollectionEqual(self, response, items_list):
|
||||
self.assertEqual(response.json, {"items": items_list})
|
||||
|
||||
def getAndAssertTableRowAction(self, response, table_name,
|
||||
action_name, row_id):
|
||||
table = response.context[table_name + '_table']
|
||||
full_row_id = '%s__row__%s' % (table_name, row_id)
|
||||
rows = list(moves.filter(lambda x: x.id == full_row_id,
|
||||
table.get_rows()))
|
||||
self.assertEqual(1, len(rows),
|
||||
"Did not find a row matching id '%s'" % row_id)
|
||||
row_actions = table.get_row_actions(rows[0])
|
||||
|
||||
msg_args = (table_name, action_name, row_id)
|
||||
self.assertTrue(
|
||||
len(row_actions) > 0,
|
||||
"No action named '%s' found in table '%s' row '%s'" % msg_args)
|
||||
|
||||
self.assertEqual(
|
||||
1, len(row_actions),
|
||||
"Multiple actions '%s' found in table '%s' row '%s'" % msg_args)
|
||||
|
||||
return row_actions[0]
|
||||
|
||||
def getAndAssertTableAction(self, response, table_name, action_name):
|
||||
|
||||
table = response.context[table_name + '_table']
|
||||
table_actions = table.get_table_actions()
|
||||
actions = list(moves.filter(lambda x: x.name == action_name,
|
||||
table_actions))
|
||||
msg_args = (table_name, action_name)
|
||||
self.assertTrue(
|
||||
len(actions) > 0,
|
||||
"No action named '%s' found in table '%s'" % msg_args)
|
||||
|
||||
self.assertEqual(
|
||||
1, len(actions),
|
||||
"More than one action named '%s' found in table '%s'" % msg_args)
|
||||
|
||||
return actions[0]
|
||||
|
||||
@staticmethod
|
||||
def mock_rest_request(**args):
|
||||
mock_args = {
|
||||
|
Loading…
Reference in New Issue
Block a user