blob: b86f29bdd41faf803bb710cc580c9eb85e2ba40a [file] [log] [blame]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001#! /usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# BitBake Toaster Implementation
6#
7# Copyright (C) 2013-2016 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22import re
23
24from django.core.urlresolvers import reverse
25from django.utils import timezone
26from tests.browser.selenium_helpers import SeleniumTestCase
27
28from orm.models import BitbakeVersion, Release, Project, Build, Target
29
Patrick Williamsc0f7c042017-02-23 20:41:17 -060030
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050031class TestAllBuildsPage(SeleniumTestCase):
32 """ Tests for all builds page /builds/ """
33
34 PROJECT_NAME = 'test project'
35 CLI_BUILDS_PROJECT_NAME = 'command line builds'
36
37 def setUp(self):
38 bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
39 branch='master', dirpath='')
40 release = Release.objects.create(name='release1',
41 bitbake_version=bbv)
42 self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
43 release=release)
44 self.default_project = Project.objects.create_project(
45 name=self.CLI_BUILDS_PROJECT_NAME,
46 release=release
47 )
48 self.default_project.is_default = True
49 self.default_project.save()
50
51 # parameters for builds to associate with the projects
52 now = timezone.now()
53
54 self.project1_build_success = {
55 'project': self.project1,
56 'started_on': now,
57 'completed_on': now,
58 'outcome': Build.SUCCEEDED
59 }
60
Patrick Williamsc0f7c042017-02-23 20:41:17 -060061 self.project1_build_failure = {
62 'project': self.project1,
63 'started_on': now,
64 'completed_on': now,
65 'outcome': Build.FAILED
66 }
67
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050068 self.default_project_build_success = {
69 'project': self.default_project,
70 'started_on': now,
71 'completed_on': now,
72 'outcome': Build.SUCCEEDED
73 }
74
Patrick Williamsc0f7c042017-02-23 20:41:17 -060075 def _get_build_time_element(self, build):
76 """
77 Return the HTML element containing the build time for a build
78 in the recent builds area
79 """
80 selector = 'div[data-latest-build-result="%s"] ' \
81 '[data-role="data-recent-build-buildtime-field"]' % build.id
82
83 # because this loads via Ajax, wait for it to be visible
84 self.wait_until_present(selector)
85
86 build_time_spans = self.find_all(selector)
87
88 self.assertEqual(len(build_time_spans), 1)
89
90 return build_time_spans[0]
91
92 def _get_row_for_build(self, build):
93 """ Get the table row for the build from the all builds table """
94 self.wait_until_present('#allbuildstable')
95
96 rows = self.find_all('#allbuildstable tr')
97
98 # look for the row with a download link on the recipe which matches the
99 # build ID
100 url = reverse('builddashboard', args=(build.id,))
101 selector = 'td.target a[href="%s"]' % url
102
103 found_row = None
104 for row in rows:
105
106 outcome_links = row.find_elements_by_css_selector(selector)
107 if len(outcome_links) == 1:
108 found_row = row
109 break
110
111 self.assertNotEqual(found_row, None)
112
113 return found_row
114
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500115 def test_show_tasks_with_suffix(self):
116 """ Task should be shown as suffix on build name """
117 build = Build.objects.create(**self.project1_build_success)
118 target = 'bash'
119 task = 'clean'
120 Target.objects.create(build=build, target=target, task=task)
121
122 url = reverse('all-builds')
123 self.get(url)
124 self.wait_until_present('td[class="target"]')
125
126 cell = self.find('td[class="target"]')
127 content = cell.get_attribute('innerHTML')
128 expected_text = '%s:%s' % (target, task)
129
130 self.assertTrue(re.search(expected_text, content),
131 '"target" cell should contain text %s' % expected_text)
132
133 def test_rebuild_buttons(self):
134 """
135 Test 'Rebuild' buttons in recent builds section
136
137 'Rebuild' button should not be shown for command-line builds,
138 but should be shown for other builds
139 """
140 build1 = Build.objects.create(**self.project1_build_success)
141 default_build = Build.objects.create(**self.default_project_build_success)
142
143 url = reverse('all-builds')
144 self.get(url)
145
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600146 # shouldn't see a rebuild button for command-line builds
147 selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % default_build.id
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500148 run_again_button = self.find_all(selector)
149 self.assertEqual(len(run_again_button), 0,
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600150 'should not see a rebuild button for cli builds')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500151
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600152 # should see a rebuild button for non-command-line builds
153 selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500154 run_again_button = self.find_all(selector)
155 self.assertEqual(len(run_again_button), 1,
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600156 'should see a rebuild button for non-cli builds')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500157
158 def test_tooltips_on_project_name(self):
159 """
160 Test tooltips shown next to project name in the main table
161
162 A tooltip should be present next to the command line
163 builds project name in the all builds page, but not for
164 other projects
165 """
166 Build.objects.create(**self.project1_build_success)
167 Build.objects.create(**self.default_project_build_success)
168
169 url = reverse('all-builds')
170 self.get(url)
171
172 # get the project name cells from the table
173 cells = self.find_all('#allbuildstable td[class="project"]')
174
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600175 selector = 'span.get-help'
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500176
177 for cell in cells:
178 content = cell.get_attribute('innerHTML')
179 help_icons = cell.find_elements_by_css_selector(selector)
180
181 if re.search(self.PROJECT_NAME, content):
182 # no help icon next to non-cli project name
183 msg = 'should not be a help icon for non-cli builds name'
184 self.assertEqual(len(help_icons), 0, msg)
185 elif re.search(self.CLI_BUILDS_PROJECT_NAME, content):
186 # help icon next to cli project name
187 msg = 'should be a help icon for cli builds name'
188 self.assertEqual(len(help_icons), 1, msg)
189 else:
190 msg = 'found unexpected project name cell in all builds table'
191 self.fail(msg)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600192
193 def test_builds_time_links(self):
194 """
195 Successful builds should have links on the time column and in the
196 recent builds area; failed builds should not have links on the time column,
197 or in the recent builds area
198 """
199 build1 = Build.objects.create(**self.project1_build_success)
200 build2 = Build.objects.create(**self.project1_build_failure)
201
202 # add some targets to these builds so they have recipe links
203 # (and so we can find the row in the ToasterTable corresponding to
204 # a particular build)
205 Target.objects.create(build=build1, target='foo')
206 Target.objects.create(build=build2, target='bar')
207
208 url = reverse('all-builds')
209 self.get(url)
210
211 # test recent builds area for successful build
212 element = self._get_build_time_element(build1)
213 links = element.find_elements_by_css_selector('a')
214 msg = 'should be a link on the build time for a successful recent build'
215 self.assertEquals(len(links), 1, msg)
216
217 # test recent builds area for failed build
218 element = self._get_build_time_element(build2)
219 links = element.find_elements_by_css_selector('a')
220 msg = 'should not be a link on the build time for a failed recent build'
221 self.assertEquals(len(links), 0, msg)
222
223 # test the time column for successful build
224 build1_row = self._get_row_for_build(build1)
225 links = build1_row.find_elements_by_css_selector('td.time a')
226 msg = 'should be a link on the build time for a successful build'
227 self.assertEquals(len(links), 1, msg)
228
229 # test the time column for failed build
230 build2_row = self._get_row_for_build(build2)
231 links = build2_row.find_elements_by_css_selector('td.time a')
232 msg = 'should not be a link on the build time for a failed build'
233 self.assertEquals(len(links), 0, msg)