Merge "Make unit testing less reliant on HTML fragments"
This commit is contained in:
commit
b06b36fcd0
@ -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