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 10import re 11 12from django.urls import reverse 13from django.utils import timezone 14from tests.browser.selenium_helpers import SeleniumTestCase 15 16from orm.models import BitbakeVersion, Release, Project, Build 17from orm.models import ProjectVariable 18 19class TestAllProjectsPage(SeleniumTestCase): 20 """ Browser tests for projects page /projects/ """ 21 22 PROJECT_NAME = 'test project' 23 CLI_BUILDS_PROJECT_NAME = 'command line builds' 24 MACHINE_NAME = 'delorean' 25 26 def setUp(self): 27 """ Add default project manually """ 28 project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None) 29 self.default_project = project 30 self.default_project.is_default = True 31 self.default_project.save() 32 33 # this project is only set for some of the tests 34 self.project = None 35 36 self.release = None 37 38 def _add_build_to_default_project(self): 39 """ Add a build to the default project (not used in all tests) """ 40 now = timezone.now() 41 build = Build.objects.create(project=self.default_project, 42 started_on=now, 43 completed_on=now) 44 build.save() 45 46 def _add_non_default_project(self): 47 """ Add another project """ 48 bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/', 49 branch='master', dirpath='') 50 self.release = Release.objects.create(name='test release', 51 branch_name='master', 52 bitbake_version=bbv) 53 self.project = Project.objects.create_project(self.PROJECT_NAME, self.release) 54 self.project.is_default = False 55 self.project.save() 56 57 # fake the MACHINE variable 58 project_var = ProjectVariable.objects.create(project=self.project, 59 name='MACHINE', 60 value=self.MACHINE_NAME) 61 project_var.save() 62 63 def _get_row_for_project(self, project_name): 64 """ Get the HTML row for a project, or None if not found """ 65 self.wait_until_present('#projectstable tbody tr') 66 rows = self.find_all('#projectstable tbody tr') 67 68 # find the row with a project name matching the one supplied 69 found_row = None 70 for row in rows: 71 if re.search(project_name, row.get_attribute('innerHTML')): 72 found_row = row 73 break 74 75 return found_row 76 77 def test_default_project_hidden(self): 78 """ 79 The default project should be hidden if it has no builds 80 and we should see the "no results" area 81 """ 82 url = reverse('all-projects') 83 self.get(url) 84 self.wait_until_visible('#empty-state-projectstable') 85 86 rows = self.find_all('#projectstable tbody tr') 87 self.assertEqual(len(rows), 0, 'should be no projects displayed') 88 89 def test_default_project_has_build(self): 90 """ The default project should be shown if it has builds """ 91 self._add_build_to_default_project() 92 93 url = reverse('all-projects') 94 self.get(url) 95 96 default_project_row = self._get_row_for_project(self.default_project.name) 97 98 self.assertNotEqual(default_project_row, None, 99 'default project "cli builds" should be in page') 100 101 def test_default_project_release(self): 102 """ 103 The release for the default project should display as 104 'Not applicable' 105 """ 106 # need a build, otherwise project doesn't display at all 107 self._add_build_to_default_project() 108 109 # another project to test, which should show release 110 self._add_non_default_project() 111 112 self.get(reverse('all-projects')) 113 self.wait_until_visible("#projectstable tr") 114 115 # find the row for the default project 116 default_project_row = self._get_row_for_project(self.default_project.name) 117 118 # check the release text for the default project 119 selector = 'span[data-project-field="release"] span.text-muted' 120 element = default_project_row.find_element_by_css_selector(selector) 121 text = element.text.strip() 122 self.assertEqual(text, 'Not applicable', 123 'release should be "not applicable" for default project') 124 125 # find the row for the default project 126 other_project_row = self._get_row_for_project(self.project.name) 127 128 # check the link in the release cell for the other project 129 selector = 'span[data-project-field="release"]' 130 element = other_project_row.find_element_by_css_selector(selector) 131 text = element.text.strip() 132 self.assertEqual(text, self.release.name, 133 'release name should be shown for non-default project') 134 135 def test_default_project_machine(self): 136 """ 137 The machine for the default project should display as 138 'Not applicable' 139 """ 140 # need a build, otherwise project doesn't display at all 141 self._add_build_to_default_project() 142 143 # another project to test, which should show machine 144 self._add_non_default_project() 145 146 self.get(reverse('all-projects')) 147 148 self.wait_until_visible("#projectstable tr") 149 150 # find the row for the default project 151 default_project_row = self._get_row_for_project(self.default_project.name) 152 153 # check the machine cell for the default project 154 selector = 'span[data-project-field="machine"] span.text-muted' 155 element = default_project_row.find_element_by_css_selector(selector) 156 text = element.text.strip() 157 self.assertEqual(text, 'Not applicable', 158 'machine should be not applicable for default project') 159 160 # find the row for the default project 161 other_project_row = self._get_row_for_project(self.project.name) 162 163 # check the link in the machine cell for the other project 164 selector = 'span[data-project-field="machine"]' 165 element = other_project_row.find_element_by_css_selector(selector) 166 text = element.text.strip() 167 self.assertEqual(text, self.MACHINE_NAME, 168 'machine name should be shown for non-default project') 169 170 def test_project_page_links(self): 171 """ 172 Test that links for the default project point to the builds 173 page /projects/X/builds for that project, and that links for 174 other projects point to their configuration pages /projects/X/ 175 """ 176 177 # need a build, otherwise project doesn't display at all 178 self._add_build_to_default_project() 179 180 # another project to test 181 self._add_non_default_project() 182 183 self.get(reverse('all-projects')) 184 185 # find the row for the default project 186 default_project_row = self._get_row_for_project(self.default_project.name) 187 188 # check the link on the name field 189 selector = 'span[data-project-field="name"] a' 190 element = default_project_row.find_element_by_css_selector(selector) 191 link_url = element.get_attribute('href').strip() 192 expected_url = reverse('projectbuilds', args=(self.default_project.id,)) 193 msg = 'link on default project name should point to builds but was %s' % link_url 194 self.assertTrue(link_url.endswith(expected_url), msg) 195 196 # find the row for the other project 197 other_project_row = self._get_row_for_project(self.project.name) 198 199 # check the link for the other project 200 selector = 'span[data-project-field="name"] a' 201 element = other_project_row.find_element_by_css_selector(selector) 202 link_url = element.get_attribute('href').strip() 203 expected_url = reverse('project', args=(self.project.id,)) 204 msg = 'link on project name should point to configuration but was %s' % link_url 205 self.assertTrue(link_url.endswith(expected_url), msg) 206