1
# Copyright 2013-2014 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Test maasserver networks views."""
6
from __future__ import (
20
from django.core.urlresolvers import reverse
21
from lxml.html import fromstring
22
from maasserver.models import Network
23
from maasserver.testing import (
28
from maasserver.testing.factory import factory
29
from maasserver.testing.testcase import MAASServerTestCase
30
from maasserver.views.networks import NetworkAdd
31
from testtools.matchers import (
40
class NetworkListingViewTest(MAASServerTestCase):
42
def test_network_list_link_present_on_homepage(self):
44
response = self.client.get(reverse('index'))
45
network_list_link = reverse('network-list')
48
get_content_links(response, element='#main-nav'))
50
def test_network_list_displays_network_details(self):
51
# Network listing displays the network name, description,
52
# network information and VLAN tag.
54
[factory.make_network() for i in range(3)]
55
networks = Network.objects.all()
56
response = self.client.get(reverse('network-list'))
60
network.description[:20],
61
'%s' % network.get_network(),
62
'%s' % network.vlan_tag if network.vlan_tag else '',
64
for network in networks]
65
details = list(itertools.chain(*details_list))
66
self.assertThat(response.content, ContainsAll(details))
68
def test_network_list_displays_sorted_list_of_networks(self):
69
# Networks are alphabetically sorted on the network list page.
71
[factory.make_network() for i in range(3)]
72
networks = Network.objects.all()
73
sorted_networks = sorted(networks, key=lambda x: x.name.lower())
74
response = self.client.get(reverse('network-list'))
76
reverse('network-view', args=[network.name])
77
for network in sorted_networks]
80
[link for link in get_content_links(response)
81
if link.startswith('/networks/')])
84
class NetworkListingViewTestNonAdmin(MAASServerTestCase):
86
def test_network_list_does_not_contain_edit_and_delete_links(self):
88
networks = [factory.make_network() for i in range(3)]
89
response = self.client.get(reverse('network-list'))
90
network_edit_links = [
91
reverse('network-edit', args=[network.name])
92
for network in networks
94
network_delete_links = [
95
reverse('network-del', args=[network.name])
96
for network in networks
98
all_links = get_content_links(response)
101
MatchesAll(*[Not(Equals(link)) for link in network_edit_links]))
104
MatchesAll(*[Not(Equals(link)) for link in network_delete_links]))
106
def test_network_list_does_not_contain_add_link(self):
108
response = self.client.get(reverse('network-list'))
109
add_link = reverse('network-add')
110
self.assertNotIn(add_link, get_content_links(response))
113
class NetworkListingViewTestAdmin(MAASServerTestCase):
115
def test_network_list_contains_edit_links(self):
116
self.client_log_in(as_admin=True)
117
networks = [factory.make_network() for i in range(3)]
118
network_edit_links = [
119
reverse('network-edit', args=[network.name])
120
for network in networks
122
network_delete_links = [
123
reverse('network-del', args=[network.name])
124
for network in networks
127
response = self.client.get(reverse('network-list'))
128
all_links = get_content_links(response)
130
self.assertThat(all_links, ContainsAll(
131
network_edit_links + network_delete_links))
133
def test_network_list_contains_add_link(self):
134
self.client_log_in(as_admin=True)
135
response = self.client.get(reverse('network-list'))
136
add_link = reverse('network-add')
137
self.assertIn(add_link, get_content_links(response))
140
class NetworkAddTestNonAdmin(MAASServerTestCase):
142
def test_cannot_add_network(self):
144
name = factory.make_name('network')
145
response = self.client.post(reverse('network-add'), {'name': name})
146
# This returns an inappropriate response (302 FOUND, redirect to the
147
# login page; should be 403 FORBIDDEN) but does not actually create the
148
# network, and that's the main thing.
149
self.assertEqual(reverse('login'), extract_redirect(response))
150
self.assertEqual([], list(Network.objects.filter(name=name)))
153
class NetworkAddTestAdmin(MAASServerTestCase):
155
def test_adds_network(self):
156
self.client_log_in(as_admin=True)
157
network = factory.getRandomNetwork()
159
'name': factory.make_name('network'),
160
'description': factory.getRandomString(),
161
'ip': "%s" % network.cidr.ip,
162
'netmask': "%s" % network.netmask,
163
'vlan_tag': factory.make_vlan_tag(),
165
response = self.client.post(reverse('network-add'), definition)
166
self.assertEqual(httplib.FOUND, response.status_code)
167
network = Network.objects.get(name=definition['name'])
169
[definition[key] for key in sorted(definition)],
170
[getattr(network, key) for key in sorted(definition)])
171
self.assertEqual(reverse('network-list'), extract_redirect(response))
173
def test_get_success_url_returns_valid_url(self):
174
self.client_log_in(as_admin=True)
175
url = NetworkAdd().get_success_url()
176
self.assertIn("/networks", url)
179
class NetworkDetailViewTest(MAASServerTestCase):
181
def test_network_detail_displays_network_detail(self):
182
# The Network detail view displays the network name and the network
185
network = factory.make_network()
186
response = self.client.get(
187
reverse('network-view', args=[network.name]))
188
self.assertThat(response.content, ContainsAll(
189
[network.name, network.description]))
191
def test_network_detail_displays_node_count(self):
193
network = factory.make_network()
194
[factory.make_node(networks=[network]) for i in range(12)]
195
response = self.client.get(
196
reverse('network-view', args=[network.name]))
197
document = fromstring(response.content)
198
count_text = document.get_element_by_id("nodecount").text_content()
199
self.assertThat(count_text, Contains('12'))
202
class NetworkDetailViewNonAdmin(MAASServerTestCase):
204
def test_network_detail_does_not_contain_edit_link(self):
206
network = factory.make_network()
207
response = self.client.get(
208
reverse('network-view', args=[network.name]))
209
network_edit_link = reverse('network-edit', args=[network.name])
210
self.assertNotIn(network_edit_link, get_content_links(response))
212
def test_network_detail_does_not_contain_delete_link(self):
214
network = factory.make_network()
215
response = self.client.get(
216
reverse('network-view', args=[network.name]))
217
network_delete_link = reverse('network-del', args=[network.name])
218
self.assertNotIn(network_delete_link, get_content_links(response))
221
class NetworkDetailViewAdmin(MAASServerTestCase):
223
def test_network_detail_contains_edit_link(self):
224
self.client_log_in(as_admin=True)
225
network = factory.make_network()
226
response = self.client.get(
227
reverse('network-view', args=[network.name]))
228
network_edit_link = reverse('network-edit', args=[network.name])
229
self.assertIn(network_edit_link, get_content_links(response))
231
def test_network_detail_contains_delete_link(self):
232
self.client_log_in(as_admin=True)
233
network = factory.make_network()
234
response = self.client.get(
235
reverse('network-view', args=[network.name]))
236
network_delete_link = reverse('network-del', args=[network.name])
237
self.assertIn(network_delete_link, get_content_links(response))
240
class NetworkEditNonAdminTest(MAASServerTestCase):
242
def test_cannot_access_network_edit(self):
244
network = factory.make_network()
245
response = self.client.post(
246
reverse('network-edit', args=[network.name]))
247
self.assertEqual(reverse('login'), extract_redirect(response))
250
class NetworkEditAdminTest(MAASServerTestCase):
252
def test_network_edit(self):
253
self.client_log_in(as_admin=True)
254
network = factory.make_network()
255
new_name = factory.make_name('name')
256
new_description = factory.make_name('description')
257
response = self.client.post(
258
reverse('network-edit', args=[network.name]),
261
'description': new_description,
264
reverse('network-list'), extract_redirect(response),
266
network = reload_object(network)
268
(new_name, new_description),
269
(network.name, network.description),
273
class NetworkDeleteNonAdminTest(MAASServerTestCase):
275
def test_cannot_delete(self):
277
network = factory.make_network()
278
response = self.client.post(
279
reverse('network-del', args=[network.name]))
280
self.assertEqual(reverse('login'), extract_redirect(response))
281
self.assertIsNotNone(reload_object(network))
284
class NetworkDeleteAdminTest(MAASServerTestCase):
286
def test_deletes_network(self):
287
self.client_log_in(as_admin=True)
288
network = factory.make_network()
289
response = self.client.post(
290
reverse('network-del', args=[network.name]),
292
self.assertEqual(httplib.FOUND, response.status_code)
293
self.assertIsNone(reload_object(network))
295
def test_redirects_to_listing(self):
296
self.client_log_in(as_admin=True)
297
network = factory.make_network()
298
response = self.client.post(
299
reverse('network-del', args=[network.name]),
301
self.assertEqual(reverse('network-list'), extract_redirect(response))