1
# Copyright 2012-2014 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Test maasserver nodes views."""
6
from __future__ import (
17
from django.core.urlresolvers import reverse
18
from lxml.etree import XPath
19
from lxml.html import fromstring
20
from maasserver.testing import get_content_links
21
from maasserver.testing.factory import factory
22
from maasserver.testing.testcase import MAASServerTestCase
23
from maasserver.views import tags as tags_views
24
from maastesting.djangotestcase import count_queries
25
from testtools.matchers import ContainsAll
28
class TagViewsTest(MAASServerTestCase):
30
def test_view_tag_displays_tag_info(self):
31
# The tag page features the basic information about the tag.
33
tag = factory.make_tag(
35
comment='Human description of the tag',
37
tag_link = reverse('tag-view', args=[tag.name])
38
response = self.client.get(tag_link)
39
doc = fromstring(response.content)
40
content_text = doc.cssselect('#content')[0].text_content()
42
content_text, ContainsAll([tag.comment, tag.definition]))
44
def test_view_tag_includes_node_links(self):
46
tag = factory.make_tag()
47
node = factory.make_node()
49
mac = factory.make_mac_address(node=node).mac_address
50
tag_link = reverse('tag-view', args=[tag.name])
51
node_link = reverse('node-view', args=[node.system_id])
52
response = self.client.get(tag_link)
53
doc = fromstring(response.content)
54
content_text = doc.cssselect('#content')[0].text_content()
56
content_text, ContainsAll([unicode(mac), '%s' % node.hostname]))
57
self.assertNotIn(node.system_id, content_text)
58
self.assertIn(node_link, get_content_links(response))
60
def test_view_tag_num_queries_is_independent_of_num_nodes(self):
62
tag = factory.make_tag()
63
tag_link = reverse('tag-view', args=[tag.name])
64
nodegroup = factory.make_node_group()
65
nodes = [factory.make_node(nodegroup=nodegroup, mac=True)
67
for node in nodes[:10]:
69
num_queries, response = count_queries(self.client.get, tag_link)
72
len([link for link in get_content_links(response)
73
if link.startswith('/nodes/node')]))
74
# Need to get the tag, and the nodes, and the macs of the nodes
75
self.assertTrue(num_queries > 3)
76
for node in nodes[10:]:
78
num_bonus_queries, response = count_queries(
79
self.client.get, tag_link)
80
self.assertEqual(num_queries, num_bonus_queries)
83
len([link for link in get_content_links(response)
84
if link.startswith('/nodes/node')]))
86
def test_view_tag_hides_private_nodes(self):
88
tag = factory.make_tag()
89
node = factory.make_node()
90
node2 = factory.make_node(owner=factory.make_user())
93
tag_link = reverse('tag-view', args=[tag.name])
94
response = self.client.get(tag_link)
95
doc = fromstring(response.content)
96
content_text = doc.cssselect('#content')[0].text_content()
97
self.assertIn(node.hostname, content_text)
98
self.assertNotIn(node2.hostname, content_text)
100
def test_view_tag_shows_kernel_params(self):
102
tag = factory.make_tag(kernel_opts='--test tag params')
103
node = factory.make_node()
105
tag_link = reverse('tag-view', args=[tag.name])
106
response = self.client.get(tag_link)
107
doc = fromstring(response.content)
108
kernel_opts = doc.cssselect('.kernel-opts-tag')[0].text_content()
109
self.assertIn('Kernel Parameters', kernel_opts)
110
self.assertIn(tag.kernel_opts, kernel_opts)
112
def test_view_tag_paginates_nodes(self):
113
"""Listing of nodes with tag is split across multiple pages
115
Copy-coded from NodeViewsTest.test_node_list_paginates evilly.
118
# Set a very small page size to save creating lots of nodes
120
self.patch(tags_views.TagView, 'paginate_by', page_size)
121
tag = factory.make_tag()
123
factory.make_node(created="2012-10-12 12:00:%02d" % i)
124
for i in range(page_size * 2 + 1)
128
# Order node links with newest first as the view is expected to
130
reverse('node-view', args=[node.system_id])
131
for node in reversed(nodes)
133
expr_page_anchors = XPath("//div[@class='pagination']//a")
134
# Fetch first page, should link newest two nodes and page 2
135
response = self.client.get(reverse('tag-view', args=[tag.name]))
136
page1 = fromstring(response.content)
138
node_links[:page_size],
139
get_content_links(response, '.node-column'))
141
[("next", "?page=2"), ("last", "?page=3")],
142
[(a.text.lower(), a.get("href"))
143
for a in expr_page_anchors(page1)])
144
# Fetch second page, should link next nodes and adjacent pages
145
response = self.client.get(
146
reverse('tag-view', args=[tag.name]), {"page": 2})
147
page2 = fromstring(response.content)
149
node_links[page_size:page_size * 2],
150
get_content_links(response, '.node-column'))
152
[("first", "."), ("previous", "."),
153
("next", "?page=3"), ("last", "?page=3")],
154
[(a.text.lower(), a.get("href"))
155
for a in expr_page_anchors(page2)])
156
# Fetch third page, should link oldest node and node list page
157
response = self.client.get(
158
reverse('tag-view', args=[tag.name]), {"page": 3})
159
page3 = fromstring(response.content)
161
node_links[page_size * 2:],
162
get_content_links(response, '.node-column'))
164
[("first", "."), ("previous", "?page=2")],
165
[(a.text.lower(), a.get("href"))
166
for a in expr_page_anchors(page3)])