aboutsummaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorElliot Smith <elliot.smith@intel.com>2016-01-15 13:01:05 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-01-15 16:30:01 +0000
commitc4b50111e9887c4d69f6a8b5fb50824fc44f7128 (patch)
tree76073d697e3161606847c629ecf3747928398be5 /bitbake
parent88a262cbd231b452f0b50cc37bec7189e5796710 (diff)
downloadopenembedded-core-contrib-c4b50111e9887c4d69f6a8b5fb50824fc44f7128.tar.gz
bitbake: toaster tests: fix Django tests for new ToasterTable pages
The Django command-line tests can no longer test the content of the projects/, builds/ and projectbuilds/ pages, as ToasterTable pages are populated by JavaScript. Fix/remove affected tests by converting them to tests on the JSON returned by the ToasterTable. [YOCTO #8738] (Bitbake rev: 85efa9530fa6181855e051bfd14de1c15db9c3b7) Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/toaster/toastergui/tests.py265
1 files changed, 180 insertions, 85 deletions
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py
index c927fe1d8d..0987721180 100644
--- a/bitbake/lib/toaster/toastergui/tests.py
+++ b/bitbake/lib/toaster/toastergui/tests.py
@@ -38,11 +38,14 @@ import toastergui
from toastergui.tables import SoftwareRecipesTable
import json
+from datetime import timedelta
from bs4 import BeautifulSoup
import re
import string
+import json
PROJECT_NAME = "test project"
+PROJECT_NAME2 = "test project 2"
CLI_BUILDS_PROJECT_NAME = 'Command line builds'
class ViewTests(TestCase):
@@ -54,14 +57,46 @@ class ViewTests(TestCase):
release = Release.objects.create(name="test release",
branch_name="master",
bitbake_version=bbv)
+ release2 = Release.objects.create(name="test release 2",
+ branch_name="master",
+ bitbake_version=bbv)
+
self.project = Project.objects.create_project(name=PROJECT_NAME,
release=release)
+
+ self.project2 = Project.objects.create_project(name=PROJECT_NAME2,
+ release=release2)
+
now = timezone.now()
+ later = now + timedelta(days=1)
build = Build.objects.create(project=self.project,
started_on=now,
completed_on=now)
+ # for testing BuildsTable
+ build1 = Build.objects.create(project=self.project,
+ started_on=now,
+ completed_on=now,
+ outcome=Build.SUCCEEDED,
+ machine="raspberrypi2")
+
+ Build.objects.create(project=self.project,
+ started_on=later,
+ completed_on=later,
+ outcome=Build.FAILED,
+ machine="qemux86")
+
+ Build.objects.create(project=self.project2,
+ started_on=later,
+ completed_on=later,
+ outcome=Build.SUCCEEDED,
+ machine="qemux86")
+
+ # to test sorting by errors and warnings in BuildsTable
+ LogMessage.objects.create(build=build1, level=LogMessage.WARNING)
+ LogMessage.objects.create(build=build1, level=LogMessage.ERROR)
+
layersrc = LayerSource.objects.create(sourcetype=LayerSource.TYPE_IMPORTED)
self.priority = ReleaseLayerSourcePriority.objects.create(release=release,
layer_source=layersrc)
@@ -172,8 +207,7 @@ class ViewTests(TestCase):
response = self.client.get(reverse('all-projects'), follow=True)
self.assertEqual(response.status_code, 200)
self.assertTrue(response['Content-Type'].startswith('text/html'))
- self.assertTemplateUsed(response, "projects.html")
- self.assertTrue(PROJECT_NAME in response.content)
+ self.assertTemplateUsed(response, "projects-toastertable.html")
def test_get_json_call_returns_json(self):
"""Test for all projects output in json format"""
@@ -191,13 +225,6 @@ class ViewTests(TestCase):
self.assertTrue(PROJECT_NAME in [x["name"] for x in data["rows"]])
self.assertTrue("id" in data["rows"][0])
- self.assertEqual(sorted(data["rows"][0]),
- ['bitbake_version_id', 'created', 'id',
- 'is_default', 'layersTypeAheadUrl', 'name',
- 'num_builds', 'projectBuildsUrl', 'projectPageUrl',
- 'recipesTypeAheadUrl', 'release_id',
- 'short_description', 'updated', 'user_id'])
-
def test_typeaheads(self):
"""Test typeahead ReST API"""
layers_url = reverse('xhr_layerstypeahead', args=(self.project.id,))
@@ -450,7 +477,7 @@ class ViewTests(TestCase):
all_data = get_data(table)
self.assertTrue(len(all_data['rows']) > 1,
- "Cannot test on a table with < 1 row")
+ "Cannot test on the table %s with < 1 row" % name)
if table.default_orderby:
row_one = all_data['rows'][0][table.default_orderby.strip("-")]
@@ -512,16 +539,20 @@ class ViewTests(TestCase):
# This is the name of the filter:action
# e.g. project_filter:not_in_project
filter_string = "%s:%s" % (column['filter_name'],
- filter_action['name'])
+ filter_action['action_name'])
# Now get the data with the filter applied
filtered_data = get_data(table_cls(),
{"filter" : filter_string})
- self.assertEqual(len(filtered_data['rows']),
- int(filter_action['count']),
- "We added a table filter for %s but "
- "the number of rows returned was not "
- "what the filter info said there "
- "would be" % name)
+
+ # date range filter actions can't specify the
+ # number of results they return, so their count is 0
+ if filter_action['count'] != None:
+ self.assertEqual(len(filtered_data['rows']),
+ int(filter_action['count']),
+ "We added a table filter for %s but "
+ "the number of rows returned was not "
+ "what the filter info said there "
+ "would be" % name)
# Test search functionality on the table
@@ -673,6 +704,10 @@ class AllProjectsPageTests(TestCase):
value=self.MACHINE_NAME)
project_var.save()
+ def _get_row_for_project(self, data, project_id):
+ """ Get the object representing the table data for a project """
+ return [row for row in data['rows'] if row['id'] == project_id][0]
+
def test_default_project_hidden(self):
""" The default project should be hidden if it has no builds """
params = {"count": 10, "orderby": "updated:-", "page": 1}
@@ -688,11 +723,20 @@ class AllProjectsPageTests(TestCase):
self._add_build_to_default_project()
params = {"count": 10, "orderby": "updated:-", "page": 1}
- response = self.client.get(reverse('all-projects'), params)
- self.assertTrue('tr class="data"' in response.content,
- 'should be a project row in the page')
- self.assertTrue(CLI_BUILDS_PROJECT_NAME in response.content,
+ response = self.client.get(
+ reverse('all-projects'),
+ {'format': 'json'},
+ params
+ )
+
+ data = json.loads(response.content)
+
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(data, self.default_project.id)
+
+ # check its name template has the correct text
+ self.assertEqual(default_project_row['name'], CLI_BUILDS_PROJECT_NAME,
'default project "cli builds" should be in page')
def test_default_project_release(self):
@@ -706,24 +750,32 @@ class AllProjectsPageTests(TestCase):
# another project to test, which should show release
self._add_non_default_project()
- response = self.client.get(reverse('all-projects'), follow=True)
- soup = BeautifulSoup(response.content)
+ response = self.client.get(
+ reverse('all-projects'),
+ {'format': 'json'},
+ follow=True
+ )
- # check the release cell for the default project
- attrs = {'data-project': str(self.default_project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- self.assertEqual(len(rows), 1, 'should be one row for default project')
- cells = rows[0].find_all('td', attrs={'data-project-field': 'release'})
- self.assertEqual(len(cells), 1, 'should be one release cell')
- text = cells[0].select('span.muted')[0].text
+ data = json.loads(response.content)
+
+ # used to find the correct span in the template output
+ attrs = {'data-project-field': 'release'}
+
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(data, self.default_project.id)
+
+ # check the release text for the default project
+ soup = BeautifulSoup(default_project_row['static:release'])
+ text = soup.find('span', attrs=attrs).select('span.muted')[0].text
self.assertEqual(text, 'Not applicable',
'release should be not applicable for default project')
+ # find the row for the default project
+ other_project_row = self._get_row_for_project(data, self.project.id)
+
# check the link in the release cell for the other project
- attrs = {'data-project': str(self.project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- cells = rows[0].find_all('td', attrs={'data-project-field': 'release'})
- text = cells[0].select('a')[0].text
+ soup = BeautifulSoup(other_project_row['static:release'])
+ text = soup.find('span', attrs=attrs).select('a')[0].text.strip()
self.assertEqual(text, self.release.name,
'release name should be shown for non-default project')
@@ -738,24 +790,32 @@ class AllProjectsPageTests(TestCase):
# another project to test, which should show machine
self._add_non_default_project()
- response = self.client.get(reverse('all-projects'), follow=True)
- soup = BeautifulSoup(response.content)
+ response = self.client.get(
+ reverse('all-projects'),
+ {'format': 'json'},
+ follow=True
+ )
+
+ data = json.loads(response.content)
+
+ # used to find the correct span in the template output
+ attrs = {'data-project-field': 'machine'}
+
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(data, self.default_project.id)
# check the machine cell for the default project
- attrs = {'data-project': str(self.default_project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- self.assertEqual(len(rows), 1, 'should be one row for default project')
- cells = rows[0].find_all('td', attrs={'data-project-field': 'machine'})
- self.assertEqual(len(cells), 1, 'should be one machine cell')
- text = cells[0].select('span.muted')[0].text
+ soup = BeautifulSoup(default_project_row['static:machine'])
+ text = soup.find('span', attrs=attrs).select('span.muted')[0].text.strip()
self.assertEqual(text, 'Not applicable',
- 'machine should be not applicable for default project')
+ 'machine should be not applicable for default project')
+
+ # find the row for the default project
+ other_project_row = self._get_row_for_project(data, self.project.id)
# check the link in the machine cell for the other project
- attrs = {'data-project': str(self.project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- cells = rows[0].find_all('td', attrs={'data-project-field': 'machine'})
- text = cells[0].select('a')[0].text
+ soup = BeautifulSoup(other_project_row['static:machine'])
+ text = soup.find('span', attrs=attrs).find('a').text.strip()
self.assertEqual(text, self.MACHINE_NAME,
'machine name should be shown for non-default project')
@@ -769,24 +829,33 @@ class AllProjectsPageTests(TestCase):
# need a build, otherwise project doesn't display at all
self._add_build_to_default_project()
- # another project to test, which should show machine
+ # another project to test
self._add_non_default_project()
- response = self.client.get(reverse('all-projects'), follow=True)
- soup = BeautifulSoup(response.content)
+ response = self.client.get(
+ reverse('all-projects'),
+ {'format': 'json'},
+ follow=True
+ )
+
+ data = json.loads(response.content)
- # link for default project
- row = soup.find('tr', attrs={'data-project': self.default_project.id})
- cell = row.find('td', attrs={'data-project-field': 'name'})
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(data, self.default_project.id)
+
+ # check the link on the name field
+ soup = BeautifulSoup(default_project_row['static:name'])
expected_url = reverse('projectbuilds', args=(self.default_project.id,))
- self.assertEqual(cell.find('a')['href'], expected_url,
+ self.assertEqual(soup.find('a')['href'], expected_url,
'link on default project name should point to builds')
- # link for other project
- row = soup.find('tr', attrs={'data-project': self.project.id})
- cell = row.find('td', attrs={'data-project-field': 'name'})
+ # find the row for the other project
+ other_project_row = self._get_row_for_project(data, self.project.id)
+
+ # check the link for the other project
+ soup = BeautifulSoup(other_project_row['static:name'])
expected_url = reverse('project', args=(self.project.id,))
- self.assertEqual(cell.find('a')['href'], expected_url,
+ self.assertEqual(soup.find('a')['href'], expected_url,
'link on project name should point to configuration')
class ProjectBuildsPageTests(TestCase):
@@ -846,9 +915,9 @@ class ProjectBuildsPageTests(TestCase):
def _get_rows_for_project(self, project_id):
""" Helper to retrieve HTML rows for a project """
url = reverse("projectbuilds", args=(project_id,))
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
- return soup.select('tr[class="data"]')
+ response = self.client.get(url, {'format': 'json'}, follow=True)
+ data = json.loads(response.content)
+ return data['rows']
def test_show_builds_for_project(self):
""" Builds for a project should be displayed """
@@ -889,10 +958,14 @@ class ProjectBuildsPageTests(TestCase):
""" Task should be shown as suffix on build name """
build = Build.objects.create(**self.project1_build_success)
Target.objects.create(build=build, target='bash', task='clean')
- url = reverse("projectbuilds", args=(self.project1.id,))
- response = self.client.get(url, follow=True)
- result = re.findall('^ +bash:clean$', response.content, re.MULTILINE)
- self.assertEqual(len(result), 2)
+
+ url = reverse('projectbuilds', args=(self.project1.id,))
+ response = self.client.get(url, {'format': 'json'}, follow=True)
+ data = json.loads(response.content)
+ cell = data['rows'][0]['static:target']
+
+ result = re.findall('^ +bash:clean', cell, re.MULTILINE)
+ self.assertEqual(len(result), 1)
def test_cli_builds_hides_tabs(self):
"""
@@ -952,32 +1025,46 @@ class AllBuildsPageTests(TestCase):
"outcome": Build.SUCCEEDED
}
+ def _get_row_for_build(self, data, build_id):
+ """ Get the object representing the table data for a project """
+ return [row for row in data['rows']
+ if row['id'] == build_id][0]
+
def test_show_tasks_in_allbuilds(self):
""" Task should be shown as suffix on build name """
build = Build.objects.create(**self.project1_build_success)
Target.objects.create(build=build, target='bash', task='clean')
+
url = reverse('all-builds')
- response = self.client.get(url, follow=True)
- result = re.findall('bash:clean', response.content, re.MULTILINE)
- self.assertEqual(len(result), 3)
+ response = self.client.get(url, {'format': 'json'}, follow=True)
+ data = json.loads(response.content)
+ cell = data['rows'][0]['static:target']
- def test_no_run_again_for_cli_build(self):
- """ "Run again" button should not be shown for command-line builds """
- build = Build.objects.create(**self.default_project_build_success)
+ result = re.findall('bash:clean', cell, re.MULTILINE)
+ self.assertEqual(len(result), 1)
+
+ def test_run_again(self):
+ """
+ "Run again" button should not be shown for command-line builds,
+ but should be shown for other builds
+ """
+ build1 = Build.objects.create(**self.project1_build_success)
+ default_build = Build.objects.create(**self.default_project_build_success)
url = reverse('all-builds')
response = self.client.get(url, follow=True)
soup = BeautifulSoup(response.content)
- attrs = {'data-latest-build-result': build.id}
- result = soup.find('div', attrs=attrs)
-
# shouldn't see a run again button for command-line builds
+ attrs = {'data-latest-build-result': default_build.id}
+ result = soup.find('div', attrs=attrs)
run_again_button = result.select('button')
self.assertEqual(len(run_again_button), 0)
- # should see a help icon for command-line builds
- help_icon = result.select('i.get-help-green')
- self.assertEqual(len(help_icon), 1)
+ # should see a run again button for non-command-line builds
+ attrs = {'data-latest-build-result': build1.id}
+ result = soup.find('div', attrs=attrs)
+ run_again_button = result.select('button')
+ self.assertEqual(len(run_again_button), 1)
def test_tooltips_on_project_name(self):
"""
@@ -989,20 +1076,28 @@ class AllBuildsPageTests(TestCase):
default_build = Build.objects.create(**self.default_project_build_success)
url = reverse('all-builds')
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
+ response = self.client.get(url, {'format': 'json'}, follow=True)
+ data = json.loads(response.content)
+
+ # get the data row for the non-command-line builds project
+ other_project_row = self._get_row_for_build(data, build1.id)
+
+ # make sure there is some HTML
+ soup = BeautifulSoup(other_project_row['static:project'])
+ self.assertEqual(len(soup.select('a')), 1,
+ 'should be a project name link')
# no help icon on non-default project name
- result = soup.find('tr', attrs={'data-table-build-result': build1.id})
- name = result.select('td.project-name')[0]
- icons = name.select('i.get-help')
+ icons = soup.select('i.get-help')
self.assertEqual(len(icons), 0,
'should not be a help icon for non-cli builds name')
+ # get the data row for the command-line builds project
+ default_project_row = self._get_row_for_build(data, default_build.id)
+
# help icon on default project name
- result = soup.find('tr', attrs={'data-table-build-result': default_build.id})
- name = result.select('td.project-name')[0]
- icons = name.select('i.get-help')
+ soup = BeautifulSoup(default_project_row['static:project'])
+ icons = soup.select('i.get-help')
self.assertEqual(len(icons), 1,
'should be a help icon for cli builds name')