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 10from datetime import datetime 11 12from django.urls import reverse 13from django.utils import timezone 14from tests.browser.selenium_helpers import SeleniumTestCase 15from orm.models import BitbakeVersion, Release, Project, Build 16 17class TestToasterTableUI(SeleniumTestCase): 18 """ 19 Tests for the UI elements of ToasterTable (sorting etc.); 20 note that the tests cover generic functionality of ToasterTable which 21 manifests as UI elements in the browser, and can only be tested via 22 Selenium. 23 """ 24 25 def setUp(self): 26 pass 27 28 def _get_orderby_heading(self, table): 29 """ 30 Get the current order by finding the column heading in <table> with 31 the sorted class on it. 32 33 table: WebElement for a ToasterTable 34 """ 35 selector = 'thead a.sorted' 36 heading = table.find_element_by_css_selector(selector) 37 return heading.get_attribute('innerHTML').strip() 38 39 def _get_datetime_from_cell(self, row, selector): 40 """ 41 Return the value in the cell selected by <selector> on <row> as a 42 datetime. 43 44 row: <tr> WebElement for a row in the ToasterTable 45 selector: CSS selector to use to find the cell containing the date time 46 string 47 """ 48 cell = row.find_element_by_css_selector(selector) 49 cell_text = cell.get_attribute('innerHTML').strip() 50 return datetime.strptime(cell_text, '%d/%m/%y %H:%M') 51 52 def test_revert_orderby(self): 53 """ 54 Test that sort order for a table reverts to the default sort order 55 if the current sort column is hidden. 56 """ 57 now = timezone.now() 58 later = now + timezone.timedelta(hours=1) 59 even_later = later + timezone.timedelta(hours=1) 60 61 bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/', 62 branch='master', dirpath='') 63 release = Release.objects.create(name='test release', 64 branch_name='master', 65 bitbake_version=bbv) 66 67 project = Project.objects.create_project('project', release) 68 69 # set up two builds which will order differently when sorted by 70 # started_on or completed_on 71 72 # started first, finished last 73 build1 = Build.objects.create(project=project, 74 started_on=now, 75 completed_on=even_later, 76 outcome=Build.SUCCEEDED) 77 78 # started second, finished first 79 build2 = Build.objects.create(project=project, 80 started_on=later, 81 completed_on=later, 82 outcome=Build.SUCCEEDED) 83 84 url = reverse('all-builds') 85 self.get(url) 86 table = self.wait_until_visible('#allbuildstable') 87 88 # check ordering (default is by -completed_on); so build1 should be 89 # first as it finished last 90 active_heading = self._get_orderby_heading(table) 91 self.assertEqual(active_heading, 'Completed on', 92 'table should be sorted by "Completed on" by default') 93 94 row_selector = '#allbuildstable tbody tr' 95 cell_selector = 'td.completed_on' 96 97 rows = self.find_all(row_selector) 98 row1_completed_on = self._get_datetime_from_cell(rows[0], cell_selector) 99 row2_completed_on = self._get_datetime_from_cell(rows[1], cell_selector) 100 self.assertTrue(row1_completed_on > row2_completed_on, 101 'table should be sorted by -completed_on') 102 103 # turn on started_on column 104 self.click('#edit-columns-button') 105 self.click('#checkbox-started_on') 106 107 # sort by started_on column 108 links = table.find_elements_by_css_selector('th.started_on a') 109 for link in links: 110 if link.get_attribute('innerHTML').strip() == 'Started on': 111 link.click() 112 break 113 114 # wait for table data to reload in response to new sort 115 self.wait_until_visible('#allbuildstable') 116 117 # check ordering; build1 should be first 118 active_heading = self._get_orderby_heading(table) 119 self.assertEqual(active_heading, 'Started on', 120 'table should be sorted by "Started on"') 121 122 cell_selector = 'td.started_on' 123 124 rows = self.find_all(row_selector) 125 row1_started_on = self._get_datetime_from_cell(rows[0], cell_selector) 126 row2_started_on = self._get_datetime_from_cell(rows[1], cell_selector) 127 self.assertTrue(row1_started_on < row2_started_on, 128 'table should be sorted by started_on') 129 130 # turn off started_on column 131 self.click('#edit-columns-button') 132 self.click('#checkbox-started_on') 133 134 # wait for table data to reload in response to new sort 135 self.wait_until_visible('#allbuildstable') 136 137 # check ordering (should revert to completed_on); build2 should be first 138 active_heading = self._get_orderby_heading(table) 139 self.assertEqual(active_heading, 'Completed on', 140 'table should be sorted by "Completed on" after hiding sort column') 141 142 cell_selector = 'td.completed_on' 143 144 rows = self.find_all(row_selector) 145 row1_completed_on = self._get_datetime_from_cell(rows[0], cell_selector) 146 row2_completed_on = self._get_datetime_from_cell(rows[1], cell_selector) 147 self.assertTrue(row1_completed_on > row2_completed_on, 148 'table should be sorted by -completed_on') 149