1#! /usr/bin/env python3 2# 3# BitBake Toaster Implementation 4# 5# SPDX-License-Identifier: GPL-2.0-only 6# 7# Copyright (C) 2013-2016 Intel Corporation 8# 9 10from django.urls import reverse 11from django.utils import timezone 12from tests.browser.selenium_helpers import SeleniumTestCase 13from tests.browser.selenium_helpers_base import Wait 14from orm.models import Project, Build, Task, Recipe, Layer, Layer_Version 15from bldcontrol.models import BuildRequest 16 17class TestMostRecentBuildsStates(SeleniumTestCase): 18 """ Test states update correctly in most recent builds area """ 19 20 def _create_build_request(self): 21 project = Project.objects.get_or_create_default_project() 22 23 now = timezone.now() 24 25 build = Build.objects.create(project=project, build_name='fakebuild', 26 started_on=now, completed_on=now) 27 28 return BuildRequest.objects.create(build=build, project=project, 29 state=BuildRequest.REQ_QUEUED) 30 31 def _create_recipe(self): 32 """ Add a recipe to the database and return it """ 33 layer = Layer.objects.create() 34 layer_version = Layer_Version.objects.create(layer=layer) 35 return Recipe.objects.create(name='foo', layer_version=layer_version) 36 37 def _check_build_states(self, build_request): 38 recipes_to_parse = 10 39 url = reverse('all-builds') 40 self.get(url) 41 42 build = build_request.build 43 base_selector = '[data-latest-build-result="%s"] ' % build.id 44 45 # build queued; check shown as queued 46 selector = base_selector + '[data-build-state="Queued"]' 47 element = self.wait_until_visible(selector) 48 self.assertRegexpMatches(element.get_attribute('innerHTML'), 49 'Build queued', 'build should show queued status') 50 51 # waiting for recipes to be parsed 52 build.outcome = Build.IN_PROGRESS 53 build.recipes_to_parse = recipes_to_parse 54 build.recipes_parsed = 0 55 56 build_request.state = BuildRequest.REQ_INPROGRESS 57 build_request.save() 58 59 self.get(url) 60 61 selector = base_selector + '[data-build-state="Parsing"]' 62 element = self.wait_until_visible(selector) 63 64 bar_selector = '#recipes-parsed-percentage-bar-%s' % build.id 65 bar_element = element.find_element_by_css_selector(bar_selector) 66 self.assertEqual(bar_element.value_of_css_property('width'), '0px', 67 'recipe parse progress should be at 0') 68 69 # recipes being parsed; check parse progress 70 build.recipes_parsed = 5 71 build.save() 72 73 self.get(url) 74 75 element = self.wait_until_visible(selector) 76 bar_element = element.find_element_by_css_selector(bar_selector) 77 recipe_bar_updated = lambda driver: \ 78 bar_element.get_attribute('style') == 'width: 50%;' 79 msg = 'recipe parse progress bar should update to 50%' 80 element = Wait(self.driver).until(recipe_bar_updated, msg) 81 82 # all recipes parsed, task started, waiting for first task to finish; 83 # check status is shown as "Tasks starting..." 84 build.recipes_parsed = recipes_to_parse 85 build.save() 86 87 recipe = self._create_recipe() 88 task1 = Task.objects.create(build=build, recipe=recipe, 89 task_name='Lionel') 90 task2 = Task.objects.create(build=build, recipe=recipe, 91 task_name='Jeffries') 92 93 self.get(url) 94 95 selector = base_selector + '[data-build-state="Starting"]' 96 element = self.wait_until_visible(selector) 97 self.assertRegexpMatches(element.get_attribute('innerHTML'), 98 'Tasks starting', 'build should show "tasks starting" status') 99 100 # first task finished; check tasks progress bar 101 task1.order = 1 102 task1.save() 103 104 self.get(url) 105 106 selector = base_selector + '[data-build-state="In Progress"]' 107 element = self.wait_until_visible(selector) 108 109 bar_selector = '#build-pc-done-bar-%s' % build.id 110 bar_element = element.find_element_by_css_selector(bar_selector) 111 112 task_bar_updated = lambda driver: \ 113 bar_element.get_attribute('style') == 'width: 50%;' 114 msg = 'tasks progress bar should update to 50%' 115 element = Wait(self.driver).until(task_bar_updated, msg) 116 117 # last task finished; check tasks progress bar updates 118 task2.order = 2 119 task2.save() 120 121 self.get(url) 122 123 element = self.wait_until_visible(selector) 124 bar_element = element.find_element_by_css_selector(bar_selector) 125 task_bar_updated = lambda driver: \ 126 bar_element.get_attribute('style') == 'width: 100%;' 127 msg = 'tasks progress bar should update to 100%' 128 element = Wait(self.driver).until(task_bar_updated, msg) 129 130 def test_states_to_success(self): 131 """ 132 Test state transitions in the recent builds area for a build which 133 completes successfully. 134 """ 135 build_request = self._create_build_request() 136 137 self._check_build_states(build_request) 138 139 # all tasks complete and build succeeded; check success state shown 140 build = build_request.build 141 build.outcome = Build.SUCCEEDED 142 build.save() 143 144 selector = '[data-latest-build-result="%s"] ' \ 145 '[data-build-state="Succeeded"]' % build.id 146 element = self.wait_until_visible(selector) 147 148 def test_states_to_failure(self): 149 """ 150 Test state transitions in the recent builds area for a build which 151 completes in a failure. 152 """ 153 build_request = self._create_build_request() 154 155 self._check_build_states(build_request) 156 157 # all tasks complete and build succeeded; check fail state shown 158 build = build_request.build 159 build.outcome = Build.FAILED 160 build.save() 161 162 selector = '[data-latest-build-result="%s"] ' \ 163 '[data-build-state="Failed"]' % build.id 164 element = self.wait_until_visible(selector) 165 166 def test_states_cancelling(self): 167 """ 168 Test that most recent build area updates correctly for a build 169 which is cancelled. 170 """ 171 url = reverse('all-builds') 172 173 build_request = self._create_build_request() 174 build = build_request.build 175 176 # cancel the build 177 build_request.state = BuildRequest.REQ_CANCELLING 178 build_request.save() 179 180 self.get(url) 181 182 # check cancelling state 183 selector = '[data-latest-build-result="%s"] ' \ 184 '[data-build-state="Cancelling"]' % build.id 185 element = self.wait_until_visible(selector) 186 self.assertRegexpMatches(element.get_attribute('innerHTML'), 187 'Cancelling the build', 'build should show "cancelling" status') 188 189 # check cancelled state 190 build.outcome = Build.CANCELLED 191 build.save() 192 193 self.get(url) 194 195 selector = '[data-latest-build-result="%s"] ' \ 196 '[data-build-state="Cancelled"]' % build.id 197 element = self.wait_until_visible(selector) 198 self.assertRegexpMatches(element.get_attribute('innerHTML'), 199 'Build cancelled', 'build should show "cancelled" status') 200