test_all_builds_page.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #! /usr/bin/env python3
  2. #
  3. # BitBake Toaster Implementation
  4. #
  5. # Copyright (C) 2013-2016 Intel Corporation
  6. #
  7. # SPDX-License-Identifier: GPL-2.0-only
  8. #
  9. import re
  10. from django.urls import reverse
  11. from django.utils import timezone
  12. from tests.browser.selenium_helpers import SeleniumTestCase
  13. from orm.models import BitbakeVersion, Release, Project, Build, Target
  14. class TestAllBuildsPage(SeleniumTestCase):
  15. """ Tests for all builds page /builds/ """
  16. PROJECT_NAME = 'test project'
  17. CLI_BUILDS_PROJECT_NAME = 'command line builds'
  18. def setUp(self):
  19. bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
  20. branch='master', dirpath='')
  21. release = Release.objects.create(name='release1',
  22. bitbake_version=bbv)
  23. self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
  24. release=release)
  25. self.default_project = Project.objects.create_project(
  26. name=self.CLI_BUILDS_PROJECT_NAME,
  27. release=release
  28. )
  29. self.default_project.is_default = True
  30. self.default_project.save()
  31. # parameters for builds to associate with the projects
  32. now = timezone.now()
  33. self.project1_build_success = {
  34. 'project': self.project1,
  35. 'started_on': now,
  36. 'completed_on': now,
  37. 'outcome': Build.SUCCEEDED
  38. }
  39. self.project1_build_failure = {
  40. 'project': self.project1,
  41. 'started_on': now,
  42. 'completed_on': now,
  43. 'outcome': Build.FAILED
  44. }
  45. self.default_project_build_success = {
  46. 'project': self.default_project,
  47. 'started_on': now,
  48. 'completed_on': now,
  49. 'outcome': Build.SUCCEEDED
  50. }
  51. def _get_build_time_element(self, build):
  52. """
  53. Return the HTML element containing the build time for a build
  54. in the recent builds area
  55. """
  56. selector = 'div[data-latest-build-result="%s"] ' \
  57. '[data-role="data-recent-build-buildtime-field"]' % build.id
  58. # because this loads via Ajax, wait for it to be visible
  59. self.wait_until_present(selector)
  60. build_time_spans = self.find_all(selector)
  61. self.assertEqual(len(build_time_spans), 1)
  62. return build_time_spans[0]
  63. def _get_row_for_build(self, build):
  64. """ Get the table row for the build from the all builds table """
  65. self.wait_until_present('#allbuildstable')
  66. rows = self.find_all('#allbuildstable tr')
  67. # look for the row with a download link on the recipe which matches the
  68. # build ID
  69. url = reverse('builddashboard', args=(build.id,))
  70. selector = 'td.target a[href="%s"]' % url
  71. found_row = None
  72. for row in rows:
  73. outcome_links = row.find_elements_by_css_selector(selector)
  74. if len(outcome_links) == 1:
  75. found_row = row
  76. break
  77. self.assertNotEqual(found_row, None)
  78. return found_row
  79. def test_show_tasks_with_suffix(self):
  80. """ Task should be shown as suffix on build name """
  81. build = Build.objects.create(**self.project1_build_success)
  82. target = 'bash'
  83. task = 'clean'
  84. Target.objects.create(build=build, target=target, task=task)
  85. url = reverse('all-builds')
  86. self.get(url)
  87. self.wait_until_present('td[class="target"]')
  88. cell = self.find('td[class="target"]')
  89. content = cell.get_attribute('innerHTML')
  90. expected_text = '%s:%s' % (target, task)
  91. self.assertTrue(re.search(expected_text, content),
  92. '"target" cell should contain text %s' % expected_text)
  93. def test_rebuild_buttons(self):
  94. """
  95. Test 'Rebuild' buttons in recent builds section
  96. 'Rebuild' button should not be shown for command-line builds,
  97. but should be shown for other builds
  98. """
  99. build1 = Build.objects.create(**self.project1_build_success)
  100. default_build = Build.objects.create(**self.default_project_build_success)
  101. url = reverse('all-builds')
  102. self.get(url)
  103. # shouldn't see a rebuild button for command-line builds
  104. selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % default_build.id
  105. run_again_button = self.find_all(selector)
  106. self.assertEqual(len(run_again_button), 0,
  107. 'should not see a rebuild button for cli builds')
  108. # should see a rebuild button for non-command-line builds
  109. selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id
  110. run_again_button = self.find_all(selector)
  111. self.assertEqual(len(run_again_button), 1,
  112. 'should see a rebuild button for non-cli builds')
  113. def test_tooltips_on_project_name(self):
  114. """
  115. Test tooltips shown next to project name in the main table
  116. A tooltip should be present next to the command line
  117. builds project name in the all builds page, but not for
  118. other projects
  119. """
  120. Build.objects.create(**self.project1_build_success)
  121. Build.objects.create(**self.default_project_build_success)
  122. url = reverse('all-builds')
  123. self.get(url)
  124. # get the project name cells from the table
  125. cells = self.find_all('#allbuildstable td[class="project"]')
  126. selector = 'span.get-help'
  127. for cell in cells:
  128. content = cell.get_attribute('innerHTML')
  129. help_icons = cell.find_elements_by_css_selector(selector)
  130. if re.search(self.PROJECT_NAME, content):
  131. # no help icon next to non-cli project name
  132. msg = 'should not be a help icon for non-cli builds name'
  133. self.assertEqual(len(help_icons), 0, msg)
  134. elif re.search(self.CLI_BUILDS_PROJECT_NAME, content):
  135. # help icon next to cli project name
  136. msg = 'should be a help icon for cli builds name'
  137. self.assertEqual(len(help_icons), 1, msg)
  138. else:
  139. msg = 'found unexpected project name cell in all builds table'
  140. self.fail(msg)
  141. def test_builds_time_links(self):
  142. """
  143. Successful builds should have links on the time column and in the
  144. recent builds area; failed builds should not have links on the time column,
  145. or in the recent builds area
  146. """
  147. build1 = Build.objects.create(**self.project1_build_success)
  148. build2 = Build.objects.create(**self.project1_build_failure)
  149. # add some targets to these builds so they have recipe links
  150. # (and so we can find the row in the ToasterTable corresponding to
  151. # a particular build)
  152. Target.objects.create(build=build1, target='foo')
  153. Target.objects.create(build=build2, target='bar')
  154. url = reverse('all-builds')
  155. self.get(url)
  156. # test recent builds area for successful build
  157. element = self._get_build_time_element(build1)
  158. links = element.find_elements_by_css_selector('a')
  159. msg = 'should be a link on the build time for a successful recent build'
  160. self.assertEquals(len(links), 1, msg)
  161. # test recent builds area for failed build
  162. element = self._get_build_time_element(build2)
  163. links = element.find_elements_by_css_selector('a')
  164. msg = 'should not be a link on the build time for a failed recent build'
  165. self.assertEquals(len(links), 0, msg)
  166. # test the time column for successful build
  167. build1_row = self._get_row_for_build(build1)
  168. links = build1_row.find_elements_by_css_selector('td.time a')
  169. msg = 'should be a link on the build time for a successful build'
  170. self.assertEquals(len(links), 1, msg)
  171. # test the time column for failed build
  172. build2_row = self._get_row_for_build(build2)
  173. links = build2_row.find_elements_by_css_selector('td.time a')
  174. msg = 'should not be a link on the build time for a failed build'
  175. self.assertEquals(len(links), 0, msg)