diff options
-rw-r--r-- | bitbake/lib/toaster/tests/browser/test_all_projects_page.py | 214 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/tests.py | 197 |
2 files changed, 214 insertions, 197 deletions
diff --git a/bitbake/lib/toaster/tests/browser/test_all_projects_page.py b/bitbake/lib/toaster/tests/browser/test_all_projects_page.py new file mode 100644 index 0000000000..ed8e620db4 --- /dev/null +++ b/bitbake/lib/toaster/tests/browser/test_all_projects_page.py | |||
@@ -0,0 +1,214 @@ | |||
1 | #! /usr/bin/env python | ||
2 | # ex:ts=4:sw=4:sts=4:et | ||
3 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | ||
4 | # | ||
5 | # BitBake Toaster Implementation | ||
6 | # | ||
7 | # Copyright (C) 2013-2016 Intel Corporation | ||
8 | # | ||
9 | # This program is free software; you can redistribute it and/or modify | ||
10 | # it under the terms of the GNU General Public License version 2 as | ||
11 | # published by the Free Software Foundation. | ||
12 | # | ||
13 | # This program is distributed in the hope that it will be useful, | ||
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | # GNU General Public License for more details. | ||
17 | # | ||
18 | # You should have received a copy of the GNU General Public License along | ||
19 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | |||
22 | import re | ||
23 | |||
24 | from django.core.urlresolvers import reverse | ||
25 | from django.utils import timezone | ||
26 | from tests.browser.selenium_helpers import SeleniumTestCase | ||
27 | |||
28 | from orm.models import BitbakeVersion, Release, Project, Build | ||
29 | from orm.models import ProjectVariable | ||
30 | |||
31 | class TestAllProjectsPage(SeleniumTestCase): | ||
32 | """ Browser tests for projects page /projects/ """ | ||
33 | |||
34 | PROJECT_NAME = 'test project' | ||
35 | CLI_BUILDS_PROJECT_NAME = 'command line builds' | ||
36 | MACHINE_NAME = 'delorean' | ||
37 | |||
38 | def setUp(self): | ||
39 | """ Add default project manually """ | ||
40 | project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None) | ||
41 | self.default_project = project | ||
42 | self.default_project.is_default = True | ||
43 | self.default_project.save() | ||
44 | |||
45 | # this project is only set for some of the tests | ||
46 | self.project = None | ||
47 | |||
48 | self.release = None | ||
49 | |||
50 | def _add_build_to_default_project(self): | ||
51 | """ Add a build to the default project (not used in all tests) """ | ||
52 | now = timezone.now() | ||
53 | build = Build.objects.create(project=self.default_project, | ||
54 | started_on=now, | ||
55 | completed_on=now) | ||
56 | build.save() | ||
57 | |||
58 | def _add_non_default_project(self): | ||
59 | """ Add another project """ | ||
60 | bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/', | ||
61 | branch='master', dirpath='') | ||
62 | self.release = Release.objects.create(name='test release', | ||
63 | branch_name='master', | ||
64 | bitbake_version=bbv) | ||
65 | self.project = Project.objects.create_project(self.PROJECT_NAME, self.release) | ||
66 | self.project.is_default = False | ||
67 | self.project.save() | ||
68 | |||
69 | # fake the MACHINE variable | ||
70 | project_var = ProjectVariable.objects.create(project=self.project, | ||
71 | name='MACHINE', | ||
72 | value=self.MACHINE_NAME) | ||
73 | project_var.save() | ||
74 | |||
75 | def _get_row_for_project(self, project_name): | ||
76 | """ Get the HTML row for a project, or None if not found """ | ||
77 | self.wait_until_present('#projectstable tbody tr') | ||
78 | rows = self.find_all('#projectstable tbody tr') | ||
79 | |||
80 | # find the row with a project name matching the one supplied | ||
81 | found_row = None | ||
82 | for row in rows: | ||
83 | if re.search(project_name, row.get_attribute('innerHTML')): | ||
84 | found_row = row | ||
85 | break | ||
86 | |||
87 | return found_row | ||
88 | |||
89 | def test_default_project_hidden(self): | ||
90 | """ | ||
91 | The default project should be hidden if it has no builds | ||
92 | and we should see the "no results" area | ||
93 | """ | ||
94 | url = reverse('all-projects') | ||
95 | self.get(url) | ||
96 | self.wait_until_visible('#no-results-projectstable') | ||
97 | |||
98 | rows = self.find_all('#projectstable tbody tr') | ||
99 | self.assertEqual(len(rows), 0, 'should be no projects displayed') | ||
100 | |||
101 | def test_default_project_has_build(self): | ||
102 | """ The default project should be shown if it has builds """ | ||
103 | self._add_build_to_default_project() | ||
104 | |||
105 | url = reverse('all-projects') | ||
106 | self.get(url) | ||
107 | |||
108 | default_project_row = self._get_row_for_project(self.default_project.name) | ||
109 | |||
110 | self.assertNotEqual(default_project_row, None, | ||
111 | 'default project "cli builds" should be in page') | ||
112 | |||
113 | def test_default_project_release(self): | ||
114 | """ | ||
115 | The release for the default project should display as | ||
116 | 'Not applicable' | ||
117 | """ | ||
118 | # need a build, otherwise project doesn't display at all | ||
119 | self._add_build_to_default_project() | ||
120 | |||
121 | # another project to test, which should show release | ||
122 | self._add_non_default_project() | ||
123 | |||
124 | self.get(reverse('all-projects')) | ||
125 | |||
126 | # find the row for the default project | ||
127 | default_project_row = self._get_row_for_project(self.default_project.name) | ||
128 | |||
129 | # check the release text for the default project | ||
130 | selector = 'span[data-project-field="release"] span.muted' | ||
131 | element = default_project_row.find_element_by_css_selector(selector) | ||
132 | text = element.text.strip() | ||
133 | self.assertEqual(text, 'Not applicable', | ||
134 | 'release should be "not applicable" for default project') | ||
135 | |||
136 | # find the row for the default project | ||
137 | other_project_row = self._get_row_for_project(self.project.name) | ||
138 | |||
139 | # check the link in the release cell for the other project | ||
140 | selector = 'span[data-project-field="release"] a' | ||
141 | element = other_project_row.find_element_by_css_selector(selector) | ||
142 | text = element.text.strip() | ||
143 | self.assertEqual(text, self.release.name, | ||
144 | 'release name should be shown for non-default project') | ||
145 | |||
146 | def test_default_project_machine(self): | ||
147 | """ | ||
148 | The machine for the default project should display as | ||
149 | 'Not applicable' | ||
150 | """ | ||
151 | # need a build, otherwise project doesn't display at all | ||
152 | self._add_build_to_default_project() | ||
153 | |||
154 | # another project to test, which should show machine | ||
155 | self._add_non_default_project() | ||
156 | |||
157 | self.get(reverse('all-projects')) | ||
158 | |||
159 | # find the row for the default project | ||
160 | default_project_row = self._get_row_for_project(self.default_project.name) | ||
161 | |||
162 | # check the machine cell for the default project | ||
163 | selector = 'span[data-project-field="machine"] span.muted' | ||
164 | element = default_project_row.find_element_by_css_selector(selector) | ||
165 | text = element.text.strip() | ||
166 | self.assertEqual(text, 'Not applicable', | ||
167 | 'machine should be not applicable for default project') | ||
168 | |||
169 | # find the row for the default project | ||
170 | other_project_row = self._get_row_for_project(self.project.name) | ||
171 | |||
172 | # check the link in the machine cell for the other project | ||
173 | selector = 'span[data-project-field="machine"] a' | ||
174 | element = other_project_row.find_element_by_css_selector(selector) | ||
175 | text = element.text.strip() | ||
176 | self.assertEqual(text, self.MACHINE_NAME, | ||
177 | 'machine name should be shown for non-default project') | ||
178 | |||
179 | def test_project_page_links(self): | ||
180 | """ | ||
181 | Test that links for the default project point to the builds | ||
182 | page /projects/X/builds for that project, and that links for | ||
183 | other projects point to their configuration pages /projects/X/ | ||
184 | """ | ||
185 | |||
186 | # need a build, otherwise project doesn't display at all | ||
187 | self._add_build_to_default_project() | ||
188 | |||
189 | # another project to test | ||
190 | self._add_non_default_project() | ||
191 | |||
192 | self.get(reverse('all-projects')) | ||
193 | |||
194 | # find the row for the default project | ||
195 | default_project_row = self._get_row_for_project(self.default_project.name) | ||
196 | |||
197 | # check the link on the name field | ||
198 | selector = 'span[data-project-field="name"] a' | ||
199 | element = default_project_row.find_element_by_css_selector(selector) | ||
200 | link_url = element.get_attribute('href').strip() | ||
201 | expected_url = reverse('projectbuilds', args=(self.default_project.id,)) | ||
202 | msg = 'link on default project name should point to builds but was %s' % link_url | ||
203 | self.assertTrue(link_url.endswith(expected_url), msg) | ||
204 | |||
205 | # find the row for the other project | ||
206 | other_project_row = self._get_row_for_project(self.project.name) | ||
207 | |||
208 | # check the link for the other project | ||
209 | selector = 'span[data-project-field="name"] a' | ||
210 | element = other_project_row.find_element_by_css_selector(selector) | ||
211 | link_url = element.get_attribute('href').strip() | ||
212 | expected_url = reverse('project', args=(self.project.id,)) | ||
213 | msg = 'link on project name should point to configuration but was %s' % link_url | ||
214 | self.assertTrue(link_url.endswith(expected_url), msg) | ||
diff --git a/bitbake/lib/toaster/toastergui/tests.py b/bitbake/lib/toaster/toastergui/tests.py index 7192947326..6975ac1bfe 100644 --- a/bitbake/lib/toaster/toastergui/tests.py +++ b/bitbake/lib/toaster/toastergui/tests.py | |||
@@ -493,7 +493,6 @@ class ViewTests(TestCase): | |||
493 | "Changed page on table %s but first row is the " | 493 | "Changed page on table %s but first row is the " |
494 | "same as the previous page" % name) | 494 | "same as the previous page" % name) |
495 | 495 | ||
496 | |||
497 | class LandingPageTests(TestCase): | 496 | class LandingPageTests(TestCase): |
498 | """ Tests for redirects on the landing page """ | 497 | """ Tests for redirects on the landing page """ |
499 | # disable bogus pylint message error: | 498 | # disable bogus pylint message error: |
@@ -568,202 +567,6 @@ class LandingPageTests(TestCase): | |||
568 | self.assertTrue('/builds' in response.url, | 567 | self.assertTrue('/builds' in response.url, |
569 | 'should redirect to builds') | 568 | 'should redirect to builds') |
570 | 569 | ||
571 | class AllProjectsPageTests(TestCase): | ||
572 | """ Tests for projects page /projects/ """ | ||
573 | |||
574 | MACHINE_NAME = 'delorean' | ||
575 | |||
576 | def setUp(self): | ||
577 | """ Add default project manually """ | ||
578 | project = Project.objects.create_project(CLI_BUILDS_PROJECT_NAME, None) | ||
579 | self.default_project = project | ||
580 | self.default_project.is_default = True | ||
581 | self.default_project.save() | ||
582 | |||
583 | # this project is only set for some of the tests | ||
584 | self.project = None | ||
585 | |||
586 | self.release = None | ||
587 | |||
588 | def _add_build_to_default_project(self): | ||
589 | """ Add a build to the default project (not used in all tests) """ | ||
590 | now = timezone.now() | ||
591 | build = Build.objects.create(project=self.default_project, | ||
592 | started_on=now, | ||
593 | completed_on=now) | ||
594 | build.save() | ||
595 | |||
596 | def _add_non_default_project(self): | ||
597 | """ Add another project """ | ||
598 | bbv = BitbakeVersion.objects.create(name="test bbv", giturl="/tmp/", | ||
599 | branch="master", dirpath="") | ||
600 | self.release = Release.objects.create(name="test release", | ||
601 | branch_name="master", | ||
602 | bitbake_version=bbv) | ||
603 | self.project = Project.objects.create_project(PROJECT_NAME, self.release) | ||
604 | self.project.is_default = False | ||
605 | self.project.save() | ||
606 | |||
607 | # fake the MACHINE variable | ||
608 | project_var = ProjectVariable.objects.create(project=self.project, | ||
609 | name='MACHINE', | ||
610 | value=self.MACHINE_NAME) | ||
611 | project_var.save() | ||
612 | |||
613 | def _get_row_for_project(self, data, project_id): | ||
614 | """ Get the object representing the table data for a project """ | ||
615 | return [row for row in data['rows'] if row['id'] == project_id][0] | ||
616 | |||
617 | def test_default_project_hidden(self): | ||
618 | """ The default project should be hidden if it has no builds """ | ||
619 | params = {"count": 10, "orderby": "updated:-", "page": 1} | ||
620 | response = self.client.get(reverse('all-projects'), params) | ||
621 | |||
622 | self.assertTrue(not('tr class="data"' in response.content), | ||
623 | 'should be no project rows in the page') | ||
624 | self.assertTrue(not(CLI_BUILDS_PROJECT_NAME in response.content), | ||
625 | 'default project "cli builds" should not be in page') | ||
626 | |||
627 | def test_default_project_has_build(self): | ||
628 | """ The default project should be shown if it has builds """ | ||
629 | self._add_build_to_default_project() | ||
630 | |||
631 | params = {"count": 10, "orderby": "updated:-", "page": 1} | ||
632 | |||
633 | response = self.client.get( | ||
634 | reverse('all-projects'), | ||
635 | {'format': 'json'}, | ||
636 | params | ||
637 | ) | ||
638 | |||
639 | data = json.loads(response.content) | ||
640 | |||
641 | # find the row for the default project | ||
642 | default_project_row = self._get_row_for_project(data, self.default_project.id) | ||
643 | |||
644 | # check its name template has the correct text | ||
645 | self.assertEqual(default_project_row['name'], CLI_BUILDS_PROJECT_NAME, | ||
646 | 'default project "cli builds" should be in page') | ||
647 | |||
648 | def test_default_project_release(self): | ||
649 | """ | ||
650 | The release for the default project should display as | ||
651 | 'Not applicable' | ||
652 | """ | ||
653 | # need a build, otherwise project doesn't display at all | ||
654 | self._add_build_to_default_project() | ||
655 | |||
656 | # another project to test, which should show release | ||
657 | self._add_non_default_project() | ||
658 | |||
659 | response = self.client.get( | ||
660 | reverse('all-projects'), | ||
661 | {'format': 'json'}, | ||
662 | follow=True | ||
663 | ) | ||
664 | |||
665 | data = json.loads(response.content) | ||
666 | |||
667 | # used to find the correct span in the template output | ||
668 | attrs = {'data-project-field': 'release'} | ||
669 | |||
670 | # find the row for the default project | ||
671 | default_project_row = self._get_row_for_project(data, self.default_project.id) | ||
672 | |||
673 | # check the release text for the default project | ||
674 | soup = BeautifulSoup(default_project_row['static:release']) | ||
675 | text = soup.find('span', attrs=attrs).select('span.muted')[0].text | ||
676 | self.assertEqual(text, 'Not applicable', | ||
677 | 'release should be not applicable for default project') | ||
678 | |||
679 | # find the row for the default project | ||
680 | other_project_row = self._get_row_for_project(data, self.project.id) | ||
681 | |||
682 | # check the link in the release cell for the other project | ||
683 | soup = BeautifulSoup(other_project_row['static:release']) | ||
684 | text = soup.find('span', attrs=attrs).select('a')[0].text.strip() | ||
685 | self.assertEqual(text, self.release.name, | ||
686 | 'release name should be shown for non-default project') | ||
687 | |||
688 | def test_default_project_machine(self): | ||
689 | """ | ||
690 | The machine for the default project should display as | ||
691 | 'Not applicable' | ||
692 | """ | ||
693 | # need a build, otherwise project doesn't display at all | ||
694 | self._add_build_to_default_project() | ||
695 | |||
696 | # another project to test, which should show machine | ||
697 | self._add_non_default_project() | ||
698 | |||
699 | response = self.client.get( | ||
700 | reverse('all-projects'), | ||
701 | {'format': 'json'}, | ||
702 | follow=True | ||
703 | ) | ||
704 | |||
705 | data = json.loads(response.content) | ||
706 | |||
707 | # used to find the correct span in the template output | ||
708 | attrs = {'data-project-field': 'machine'} | ||
709 | |||
710 | # find the row for the default project | ||
711 | default_project_row = self._get_row_for_project(data, self.default_project.id) | ||
712 | |||
713 | # check the machine cell for the default project | ||
714 | soup = BeautifulSoup(default_project_row['static:machine']) | ||
715 | text = soup.find('span', attrs=attrs).select('span.muted')[0].text.strip() | ||
716 | self.assertEqual(text, 'Not applicable', | ||
717 | 'machine should be not applicable for default project') | ||
718 | |||
719 | # find the row for the default project | ||
720 | other_project_row = self._get_row_for_project(data, self.project.id) | ||
721 | |||
722 | # check the link in the machine cell for the other project | ||
723 | soup = BeautifulSoup(other_project_row['static:machine']) | ||
724 | text = soup.find('span', attrs=attrs).find('a').text.strip() | ||
725 | self.assertEqual(text, self.MACHINE_NAME, | ||
726 | 'machine name should be shown for non-default project') | ||
727 | |||
728 | def test_project_page_links(self): | ||
729 | """ | ||
730 | Test that links for the default project point to the builds | ||
731 | page /projects/X/builds for that project, and that links for | ||
732 | other projects point to their configuration pages /projects/X/ | ||
733 | """ | ||
734 | |||
735 | # need a build, otherwise project doesn't display at all | ||
736 | self._add_build_to_default_project() | ||
737 | |||
738 | # another project to test | ||
739 | self._add_non_default_project() | ||
740 | |||
741 | response = self.client.get( | ||
742 | reverse('all-projects'), | ||
743 | {'format': 'json'}, | ||
744 | follow=True | ||
745 | ) | ||
746 | |||
747 | data = json.loads(response.content) | ||
748 | |||
749 | # find the row for the default project | ||
750 | default_project_row = self._get_row_for_project(data, self.default_project.id) | ||
751 | |||
752 | # check the link on the name field | ||
753 | soup = BeautifulSoup(default_project_row['static:name']) | ||
754 | expected_url = reverse('projectbuilds', args=(self.default_project.id,)) | ||
755 | self.assertEqual(soup.find('a')['href'], expected_url, | ||
756 | 'link on default project name should point to builds') | ||
757 | |||
758 | # find the row for the other project | ||
759 | other_project_row = self._get_row_for_project(data, self.project.id) | ||
760 | |||
761 | # check the link for the other project | ||
762 | soup = BeautifulSoup(other_project_row['static:name']) | ||
763 | expected_url = reverse('project', args=(self.project.id,)) | ||
764 | self.assertEqual(soup.find('a')['href'], expected_url, | ||
765 | 'link on project name should point to configuration') | ||
766 | |||
767 | class BuildDashboardTests(TestCase): | 570 | class BuildDashboardTests(TestCase): |
768 | """ Tests for the build dashboard /build/X """ | 571 | """ Tests for the build dashboard /build/X """ |
769 | 572 | ||