summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/tests/browser
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/tests/browser')
-rw-r--r--bitbake/lib/toaster/tests/browser/selenium_helpers_base.py50
-rw-r--r--bitbake/lib/toaster/tests/browser/test_all_builds_page.py7
-rw-r--r--bitbake/lib/toaster/tests/browser/test_all_projects_page.py12
-rw-r--r--bitbake/lib/toaster/tests/browser/test_builddashboard_page.py2
-rw-r--r--bitbake/lib/toaster/tests/browser/test_landing_page.py14
-rw-r--r--bitbake/lib/toaster/tests/browser/test_layerdetails_page.py52
-rw-r--r--bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py2
-rw-r--r--bitbake/lib/toaster/tests/browser/test_new_project_page.py12
8 files changed, 80 insertions, 71 deletions
diff --git a/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py b/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
index 393be75496..6953541ab5 100644
--- a/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
+++ b/bitbake/lib/toaster/tests/browser/selenium_helpers_base.py
@@ -27,7 +27,7 @@ from selenium.webdriver.common.by import By
27from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 27from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
28from selenium.common.exceptions import NoSuchElementException, \ 28from selenium.common.exceptions import NoSuchElementException, \
29 StaleElementReferenceException, TimeoutException, \ 29 StaleElementReferenceException, TimeoutException, \
30 SessionNotCreatedException 30 SessionNotCreatedException, WebDriverException
31 31
32def create_selenium_driver(cls,browser='chrome'): 32def create_selenium_driver(cls,browser='chrome'):
33 # set default browser string based on env (if available) 33 # set default browser string based on env (if available)
@@ -90,7 +90,7 @@ class Wait(WebDriverWait):
90 Subclass of WebDriverWait with predetermined timeout and poll 90 Subclass of WebDriverWait with predetermined timeout and poll
91 frequency. Also deals with a wider variety of exceptions. 91 frequency. Also deals with a wider variety of exceptions.
92 """ 92 """
93 _TIMEOUT = 10 93 _TIMEOUT = 20
94 _POLL_FREQUENCY = 0.5 94 _POLL_FREQUENCY = 0.5
95 95
96 def __init__(self, driver, timeout=_TIMEOUT, poll=_POLL_FREQUENCY): 96 def __init__(self, driver, timeout=_TIMEOUT, poll=_POLL_FREQUENCY):
@@ -114,6 +114,9 @@ class Wait(WebDriverWait):
114 pass 114 pass
115 except StaleElementReferenceException: 115 except StaleElementReferenceException:
116 pass 116 pass
117 except WebDriverException:
118 # selenium.common.exceptions.WebDriverException: Message: unknown error: unhandled inspector error: {"code":-32000,"message":"Node with given id does not belong to the document"}
119 pass
117 120
118 time.sleep(self._poll) 121 time.sleep(self._poll)
119 if time.time() > end_time: 122 if time.time() > end_time:
@@ -183,7 +186,7 @@ class SeleniumTestCaseBase(unittest.TestCase):
183 self.driver.get(abs_url) 186 self.driver.get(abs_url)
184 187
185 try: # Ensure page is loaded before proceeding 188 try: # Ensure page is loaded before proceeding
186 self.wait_until_visible("#global-nav", poll=3) 189 self.wait_until_visible("#global-nav")
187 except NoSuchElementException: 190 except NoSuchElementException:
188 self.driver.implicitly_wait(3) 191 self.driver.implicitly_wait(3)
189 except TimeoutException: 192 except TimeoutException:
@@ -208,36 +211,43 @@ class SeleniumTestCaseBase(unittest.TestCase):
208 """ Return the element which currently has focus on the page """ 211 """ Return the element which currently has focus on the page """
209 return self.driver.switch_to.active_element 212 return self.driver.switch_to.active_element
210 213
211 def wait_until_present(self, selector, poll=0.5): 214 def wait_until_present(self, selector, timeout=Wait._TIMEOUT):
212 """ Wait until element matching CSS selector is on the page """ 215 """ Wait until element matching CSS selector is on the page """
213 is_present = lambda driver: self.find(selector) 216 is_present = lambda driver: self.find(selector)
214 msg = 'An element matching "%s" should be on the page' % selector 217 msg = 'An element matching "%s" should be on the page' % selector
215 element = Wait(self.driver, poll=poll).until(is_present, msg) 218 element = Wait(self.driver, timeout=timeout).until(is_present, msg)
216 if poll > 2:
217 time.sleep(poll) # element need more delay to be present
218 return element 219 return element
219 220
220 def wait_until_visible(self, selector, poll=1): 221 def wait_until_visible(self, selector, timeout=Wait._TIMEOUT):
221 """ Wait until element matching CSS selector is visible on the page """ 222 """ Wait until element matching CSS selector is visible on the page """
222 is_visible = lambda driver: self.find(selector).is_displayed() 223 is_visible = lambda driver: self.find(selector).is_displayed()
223 msg = 'An element matching "%s" should be visible' % selector 224 msg = 'An element matching "%s" should be visible' % selector
224 Wait(self.driver, poll=poll).until(is_visible, msg) 225 Wait(self.driver, timeout=timeout).until(is_visible, msg)
225 time.sleep(poll) # wait for visibility to settle 226 return self.find(selector)
227
228 def wait_until_not_visible(self, selector, timeout=Wait._TIMEOUT):
229 """ Wait until element matching CSS selector is not visible on the page """
230 is_visible = lambda driver: self.find(selector).is_displayed()
231 msg = 'An element matching "%s" should be visible' % selector
232 Wait(self.driver, timeout=timeout).until_not(is_visible, msg)
226 return self.find(selector) 233 return self.find(selector)
227 234
228 def wait_until_clickable(self, selector, poll=1): 235 def wait_until_clickable(self, selector, timeout=Wait._TIMEOUT):
229 """ Wait until element matching CSS selector is visible on the page """ 236 """ Wait until element matching CSS selector is visible on the page """
230 WebDriverWait( 237 WebDriverWait(self.driver, timeout=timeout).until(lambda driver: self.driver.execute_script("return jQuery.active == 0"))
231 self.driver, 238 is_clickable = lambda driver: (self.find(selector).is_displayed() and self.find(selector).is_enabled())
232 Wait._TIMEOUT, 239 msg = 'An element matching "%s" should be clickable' % selector
233 poll_frequency=poll 240 Wait(self.driver, timeout=timeout).until(is_clickable, msg)
234 ).until(
235 EC.element_to_be_clickable((By.ID, selector.removeprefix('#')
236 )
237 )
238 )
239 return self.find(selector) 241 return self.find(selector)
240 242
243 def wait_until_element_clickable(self, finder, timeout=Wait._TIMEOUT):
244 """ Wait until element is clickable """
245 WebDriverWait(self.driver, timeout=timeout).until(lambda driver: self.driver.execute_script("return jQuery.active == 0"))
246 is_clickable = lambda driver: (finder(driver).is_displayed() and finder(driver).is_enabled())
247 msg = 'A matching element never became be clickable'
248 Wait(self.driver, timeout=timeout).until(is_clickable, msg)
249 return finder(self.driver)
250
241 def wait_until_focused(self, selector): 251 def wait_until_focused(self, selector):
242 """ Wait until element matching CSS selector has focus """ 252 """ Wait until element matching CSS selector has focus """
243 is_focused = \ 253 is_focused = \
diff --git a/bitbake/lib/toaster/tests/browser/test_all_builds_page.py b/bitbake/lib/toaster/tests/browser/test_all_builds_page.py
index b9356a0344..9ab81fb11b 100644
--- a/bitbake/lib/toaster/tests/browser/test_all_builds_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_all_builds_page.py
@@ -200,6 +200,7 @@ class TestAllBuildsPage(SeleniumTestCase):
200 200
201 # should see a rebuild button for non-command-line builds 201 # should see a rebuild button for non-command-line builds
202 self.wait_until_visible('#allbuildstable tbody tr') 202 self.wait_until_visible('#allbuildstable tbody tr')
203 self.wait_until_visible('.rebuild-btn')
203 selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id 204 selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id
204 run_again_button = self.find_all(selector) 205 run_again_button = self.find_all(selector)
205 self.assertEqual(len(run_again_button), 1, 206 self.assertEqual(len(run_again_button), 1,
@@ -224,7 +225,7 @@ class TestAllBuildsPage(SeleniumTestCase):
224 225
225 url = reverse('all-builds') 226 url = reverse('all-builds')
226 self.get(url) 227 self.get(url)
227 self.wait_until_visible('#allbuildstable', poll=3) 228 self.wait_until_visible('#allbuildstable')
228 229
229 # get the project name cells from the table 230 # get the project name cells from the table
230 cells = self.find_all('#allbuildstable td[class="project"]') 231 cells = self.find_all('#allbuildstable td[class="project"]')
@@ -257,7 +258,7 @@ class TestAllBuildsPage(SeleniumTestCase):
257 258
258 url = reverse('all-builds') 259 url = reverse('all-builds')
259 self.get(url) 260 self.get(url)
260 self.wait_until_visible('#allbuildstable', poll=3) 261 self.wait_until_visible('#allbuildstable')
261 262
262 # test recent builds area for successful build 263 # test recent builds area for successful build
263 element = self._get_build_time_element(build1) 264 element = self._get_build_time_element(build1)
@@ -452,7 +453,7 @@ class TestAllBuildsPage(SeleniumTestCase):
452 def test_show_rows(row_to_show, show_row_link): 453 def test_show_rows(row_to_show, show_row_link):
453 # Check that we can show rows == row_to_show 454 # Check that we can show rows == row_to_show
454 show_row_link.select_by_value(str(row_to_show)) 455 show_row_link.select_by_value(str(row_to_show))
455 self.wait_until_visible('#allbuildstable tbody tr', poll=3) 456 self.wait_until_visible('#allbuildstable tbody tr')
456 # check at least some rows are visible 457 # check at least some rows are visible
457 self.assertTrue( 458 self.assertTrue(
458 len(self.find_all('#allbuildstable tbody tr')) > 0 459 len(self.find_all('#allbuildstable tbody tr')) > 0
diff --git a/bitbake/lib/toaster/tests/browser/test_all_projects_page.py b/bitbake/lib/toaster/tests/browser/test_all_projects_page.py
index 9ed1901cc9..05e12892be 100644
--- a/bitbake/lib/toaster/tests/browser/test_all_projects_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_all_projects_page.py
@@ -81,7 +81,7 @@ class TestAllProjectsPage(SeleniumTestCase):
81 81
82 def _get_row_for_project(self, project_name): 82 def _get_row_for_project(self, project_name):
83 """ Get the HTML row for a project, or None if not found """ 83 """ Get the HTML row for a project, or None if not found """
84 self.wait_until_visible('#projectstable tbody tr', poll=3) 84 self.wait_until_visible('#projectstable tbody tr')
85 rows = self.find_all('#projectstable tbody tr') 85 rows = self.find_all('#projectstable tbody tr')
86 86
87 # find the row with a project name matching the one supplied 87 # find the row with a project name matching the one supplied
@@ -236,7 +236,7 @@ class TestAllProjectsPage(SeleniumTestCase):
236 self.get(url) 236 self.get(url)
237 237
238 # Chseck search box is present and works 238 # Chseck search box is present and works
239 self.wait_until_visible('#projectstable tbody tr', poll=3) 239 self.wait_until_visible('#projectstable tbody tr')
240 search_box = self.find('#search-input-projectstable') 240 search_box = self.find('#search-input-projectstable')
241 self.assertTrue(search_box.is_displayed()) 241 self.assertTrue(search_box.is_displayed())
242 242
@@ -244,7 +244,7 @@ class TestAllProjectsPage(SeleniumTestCase):
244 search_box.send_keys('test project 10') 244 search_box.send_keys('test project 10')
245 search_btn = self.find('#search-submit-projectstable') 245 search_btn = self.find('#search-submit-projectstable')
246 search_btn.click() 246 search_btn.click()
247 self.wait_until_visible('#projectstable tbody tr', poll=3) 247 self.wait_until_visible('#projectstable tbody tr')
248 rows = self.find_all('#projectstable tbody tr') 248 rows = self.find_all('#projectstable tbody tr')
249 self.assertTrue(len(rows) == 1) 249 self.assertTrue(len(rows) == 1)
250 250
@@ -290,7 +290,7 @@ class TestAllProjectsPage(SeleniumTestCase):
290 ) 290 )
291 url = reverse('all-projects') 291 url = reverse('all-projects')
292 self.get(url) 292 self.get(url)
293 self.wait_until_visible('#projectstable tbody tr', poll=3) 293 self.wait_until_visible('#projectstable tbody tr')
294 294
295 # Check edit column 295 # Check edit column
296 edit_column = self.find('#edit-columns-button') 296 edit_column = self.find('#edit-columns-button')
@@ -313,7 +313,7 @@ class TestAllProjectsPage(SeleniumTestCase):
313 def test_show_rows(row_to_show, show_row_link): 313 def test_show_rows(row_to_show, show_row_link):
314 # Check that we can show rows == row_to_show 314 # Check that we can show rows == row_to_show
315 show_row_link.select_by_value(str(row_to_show)) 315 show_row_link.select_by_value(str(row_to_show))
316 self.wait_until_visible('#projectstable tbody tr', poll=3) 316 self.wait_until_visible('#projectstable tbody tr')
317 # check at least some rows are visible 317 # check at least some rows are visible
318 self.assertTrue( 318 self.assertTrue(
319 len(self.find_all('#projectstable tbody tr')) > 0 319 len(self.find_all('#projectstable tbody tr')) > 0
@@ -321,7 +321,7 @@ class TestAllProjectsPage(SeleniumTestCase):
321 321
322 url = reverse('all-projects') 322 url = reverse('all-projects')
323 self.get(url) 323 self.get(url)
324 self.wait_until_visible('#projectstable tbody tr', poll=3) 324 self.wait_until_visible('#projectstable tbody tr')
325 325
326 show_rows = self.driver.find_elements( 326 show_rows = self.driver.find_elements(
327 By.XPATH, 327 By.XPATH,
diff --git a/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py b/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py
index d838ce363a..82367108e2 100644
--- a/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py
@@ -162,7 +162,7 @@ class TestBuildDashboardPage(SeleniumTestCase):
162 """ 162 """
163 url = reverse('builddashboard', args=(build.id,)) 163 url = reverse('builddashboard', args=(build.id,))
164 self.get(url) 164 self.get(url)
165 self.wait_until_visible('#global-nav', poll=3) 165 self.wait_until_visible('#global-nav')
166 166
167 def _get_build_dashboard_errors(self, build): 167 def _get_build_dashboard_errors(self, build):
168 """ 168 """
diff --git a/bitbake/lib/toaster/tests/browser/test_landing_page.py b/bitbake/lib/toaster/tests/browser/test_landing_page.py
index 8fe5fea467..210359d561 100644
--- a/bitbake/lib/toaster/tests/browser/test_landing_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_landing_page.py
@@ -34,6 +34,7 @@ class TestLandingPage(SeleniumTestCase):
34 def test_icon_info_visible_and_clickable(self): 34 def test_icon_info_visible_and_clickable(self):
35 """ Test that the information icon is visible and clickable """ 35 """ Test that the information icon is visible and clickable """
36 self.get(reverse('landing')) 36 self.get(reverse('landing'))
37 self.wait_until_visible('#toaster-version-info-sign')
37 info_sign = self.find('#toaster-version-info-sign') 38 info_sign = self.find('#toaster-version-info-sign')
38 39
39 # check that the info sign is visible 40 # check that the info sign is visible
@@ -43,6 +44,7 @@ class TestLandingPage(SeleniumTestCase):
43 # and info modal is appearing when clicking on the info sign 44 # and info modal is appearing when clicking on the info sign
44 info_sign.click() # click on the info sign make attribute 'aria-describedby' visible 45 info_sign.click() # click on the info sign make attribute 'aria-describedby' visible
45 info_model_id = info_sign.get_attribute('aria-describedby') 46 info_model_id = info_sign.get_attribute('aria-describedby')
47 self.wait_until_visible(f'#{info_model_id}')
46 info_modal = self.find(f'#{info_model_id}') 48 info_modal = self.find(f'#{info_model_id}')
47 self.assertTrue(info_modal.is_displayed()) 49 self.assertTrue(info_modal.is_displayed())
48 self.assertTrue("Toaster version information" in info_modal.text) 50 self.assertTrue("Toaster version information" in info_modal.text)
@@ -50,6 +52,7 @@ class TestLandingPage(SeleniumTestCase):
50 def test_documentation_link_displayed(self): 52 def test_documentation_link_displayed(self):
51 """ Test that the documentation link is displayed """ 53 """ Test that the documentation link is displayed """
52 self.get(reverse('landing')) 54 self.get(reverse('landing'))
55 self.wait_until_visible('#navbar-docs')
53 documentation_link = self.find('#navbar-docs > a') 56 documentation_link = self.find('#navbar-docs > a')
54 57
55 # check that the documentation link is visible 58 # check that the documentation link is visible
@@ -65,6 +68,7 @@ class TestLandingPage(SeleniumTestCase):
65 def test_openembedded_jumbotron_link_visible_and_clickable(self): 68 def test_openembedded_jumbotron_link_visible_and_clickable(self):
66 """ Test OpenEmbedded link jumbotron is visible and clickable: """ 69 """ Test OpenEmbedded link jumbotron is visible and clickable: """
67 self.get(reverse('landing')) 70 self.get(reverse('landing'))
71 self.wait_until_visible('.jumbotron')
68 jumbotron = self.find('.jumbotron') 72 jumbotron = self.find('.jumbotron')
69 73
70 # check OpenEmbedded 74 # check OpenEmbedded
@@ -76,6 +80,7 @@ class TestLandingPage(SeleniumTestCase):
76 def test_bitbake_jumbotron_link_visible_and_clickable(self): 80 def test_bitbake_jumbotron_link_visible_and_clickable(self):
77 """ Test BitBake link jumbotron is visible and clickable: """ 81 """ Test BitBake link jumbotron is visible and clickable: """
78 self.get(reverse('landing')) 82 self.get(reverse('landing'))
83 self.wait_until_visible('.jumbotron')
79 jumbotron = self.find('.jumbotron') 84 jumbotron = self.find('.jumbotron')
80 85
81 # check BitBake 86 # check BitBake
@@ -88,6 +93,7 @@ class TestLandingPage(SeleniumTestCase):
88 def test_yoctoproject_jumbotron_link_visible_and_clickable(self): 93 def test_yoctoproject_jumbotron_link_visible_and_clickable(self):
89 """ Test Yocto Project link jumbotron is visible and clickable: """ 94 """ Test Yocto Project link jumbotron is visible and clickable: """
90 self.get(reverse('landing')) 95 self.get(reverse('landing'))
96 self.wait_until_visible('.jumbotron')
91 jumbotron = self.find('.jumbotron') 97 jumbotron = self.find('.jumbotron')
92 98
93 # check Yocto Project 99 # check Yocto Project
@@ -101,6 +107,7 @@ class TestLandingPage(SeleniumTestCase):
101 if visible and clickable 107 if visible and clickable
102 """ 108 """
103 self.get(reverse('landing')) 109 self.get(reverse('landing'))
110 self.wait_until_visible('.jumbotron')
104 jumbotron = self.find('.jumbotron') 111 jumbotron = self.find('.jumbotron')
105 112
106 # check Big magenta button 113 # check Big magenta button
@@ -119,6 +126,7 @@ class TestLandingPage(SeleniumTestCase):
119 Layer_Version.objects.create(layer=layer) 126 Layer_Version.objects.create(layer=layer)
120 127
121 self.get(reverse('landing')) 128 self.get(reverse('landing'))
129 self.wait_until_visible('.jumbotron')
122 jumbotron = self.find('.jumbotron') 130 jumbotron = self.find('.jumbotron')
123 131
124 # check Big Blue button 132 # check Big Blue button
@@ -132,6 +140,7 @@ class TestLandingPage(SeleniumTestCase):
132 def test_toaster_manual_link_visible_and_clickable(self): 140 def test_toaster_manual_link_visible_and_clickable(self):
133 """ Test Read the Toaster manual link jumbotron is visible and clickable: """ 141 """ Test Read the Toaster manual link jumbotron is visible and clickable: """
134 self.get(reverse('landing')) 142 self.get(reverse('landing'))
143 self.wait_until_visible('.jumbotron')
135 jumbotron = self.find('.jumbotron') 144 jumbotron = self.find('.jumbotron')
136 145
137 # check Read the Toaster manual 146 # check Read the Toaster manual
@@ -145,6 +154,7 @@ class TestLandingPage(SeleniumTestCase):
145 def test_contrib_to_toaster_link_visible_and_clickable(self): 154 def test_contrib_to_toaster_link_visible_and_clickable(self):
146 """ Test Contribute to Toaster link jumbotron is visible and clickable: """ 155 """ Test Contribute to Toaster link jumbotron is visible and clickable: """
147 self.get(reverse('landing')) 156 self.get(reverse('landing'))
157 self.wait_until_visible('.jumbotron')
148 jumbotron = self.find('.jumbotron') 158 jumbotron = self.find('.jumbotron')
149 159
150 # check Contribute to Toaster 160 # check Contribute to Toaster
@@ -161,6 +171,7 @@ class TestLandingPage(SeleniumTestCase):
161 => should see the landing page 171 => should see the landing page
162 """ 172 """
163 self.get(reverse('landing')) 173 self.get(reverse('landing'))
174 self.wait_until_visible('.jumbotron')
164 self.assertTrue(self.LANDING_PAGE_TITLE in self.get_page_source()) 175 self.assertTrue(self.LANDING_PAGE_TITLE in self.get_page_source())
165 176
166 def test_default_project_has_build(self): 177 def test_default_project_has_build(self):
@@ -193,6 +204,7 @@ class TestLandingPage(SeleniumTestCase):
193 user_project.save() 204 user_project.save()
194 205
195 self.get(reverse('landing')) 206 self.get(reverse('landing'))
207 self.wait_until_visible('#projectstable')
196 208
197 elements = self.find_all('#projectstable') 209 elements = self.find_all('#projectstable')
198 self.assertEqual(len(elements), 1, 'should redirect to projects') 210 self.assertEqual(len(elements), 1, 'should redirect to projects')
@@ -213,7 +225,7 @@ class TestLandingPage(SeleniumTestCase):
213 225
214 self.get(reverse('landing')) 226 self.get(reverse('landing'))
215 227
216 self.wait_until_visible("#latest-builds", poll=3) 228 self.wait_until_visible("#latest-builds")
217 elements = self.find_all('#allbuildstable') 229 elements = self.find_all('#allbuildstable')
218 self.assertEqual(len(elements), 1, 'should redirect to builds') 230 self.assertEqual(len(elements), 1, 'should redirect to builds')
219 content = self.get_page_source() 231 content = self.get_page_source()
diff --git a/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py b/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py
index 5c29548b78..6abfdef699 100644
--- a/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_layerdetails_page.py
@@ -64,7 +64,7 @@ class TestLayerDetailsPage(SeleniumTestCase):
64 args=(self.project.pk, 64 args=(self.project.pk,
65 self.imported_layer_version.pk)) 65 self.imported_layer_version.pk))
66 66
67 def _edit_layerdetails(self): 67 def test_edit_layerdetails_page(self):
68 """ Edit all the editable fields for the layer refresh the page and 68 """ Edit all the editable fields for the layer refresh the page and
69 check that the new values exist""" 69 check that the new values exist"""
70 70
@@ -100,24 +100,19 @@ class TestLayerDetailsPage(SeleniumTestCase):
100 (self.initial_values, value)) 100 (self.initial_values, value))
101 101
102 # Make sure the input visible beofre sending keys 102 # Make sure the input visible beofre sending keys
103 self.wait_until_visible("#layer-git input[type=text]") 103 self.wait_until_clickable("#layer-git input[type=text]")
104 inputs.send_keys("-edited") 104 inputs.send_keys("-edited")
105 105
106 # Save the new values 106 # Save the new values
107 for save_btn in self.find_all(".change-btn"): 107 for save_btn in self.find_all(".change-btn"):
108 save_btn.click() 108 save_btn.click()
109 109
110 try: 110 self.wait_until_visible("#save-changes-for-switch")
111 self.wait_until_visible("#save-changes-for-switch", poll=3) 111 # Ensure scrolled into view
112 btn_save_chg_for_switch = self.wait_until_clickable( 112 self.driver.execute_script('window.scrollTo({behavior: "instant", top: 0, left: 0})')
113 "#save-changes-for-switch", poll=3) 113 btn_save_chg_for_switch = self.wait_until_clickable(
114 btn_save_chg_for_switch.click() 114 "#save-changes-for-switch")
115 except ElementClickInterceptedException: 115 btn_save_chg_for_switch.click()
116 self.skipTest(
117 "save-changes-for-switch click intercepted. Element not visible or maybe covered by another element.")
118 except TimeoutException:
119 self.skipTest(
120 "save-changes-for-switch is not clickable within the specified timeout.")
121 116
122 self.wait_until_visible("#edit-layer-source") 117 self.wait_until_visible("#edit-layer-source")
123 118
@@ -147,17 +142,10 @@ class TestLayerDetailsPage(SeleniumTestCase):
147 new_dir = "/home/test/my-meta-dir" 142 new_dir = "/home/test/my-meta-dir"
148 dir_input.send_keys(new_dir) 143 dir_input.send_keys(new_dir)
149 144
150 try: 145 self.wait_until_visible("#save-changes-for-switch")
151 self.wait_until_visible("#save-changes-for-switch", poll=3) 146 btn_save_chg_for_switch = self.wait_until_clickable(
152 btn_save_chg_for_switch = self.wait_until_clickable( 147 "#save-changes-for-switch")
153 "#save-changes-for-switch", poll=3) 148 btn_save_chg_for_switch.click()
154 btn_save_chg_for_switch.click()
155 except ElementClickInterceptedException:
156 self.skipTest(
157 "save-changes-for-switch click intercepted. Element not properly visible or maybe behind another element.")
158 except TimeoutException:
159 self.skipTest(
160 "save-changes-for-switch is not clickable within the specified timeout.")
161 149
162 self.wait_until_visible("#edit-layer-source") 150 self.wait_until_visible("#edit-layer-source")
163 151
@@ -168,12 +156,6 @@ class TestLayerDetailsPage(SeleniumTestCase):
168 "Expected %s in the dir value for layer directory" % 156 "Expected %s in the dir value for layer directory" %
169 new_dir) 157 new_dir)
170 158
171 def test_edit_layerdetails_page(self):
172 try:
173 self._edit_layerdetails()
174 except ElementClickInterceptedException:
175 self.skipTest(
176 "ElementClickInterceptedException occured. Element not visible or maybe covered by another element.")
177 159
178 def test_delete_layer(self): 160 def test_delete_layer(self):
179 """ Delete the layer """ 161 """ Delete the layer """
@@ -211,6 +193,7 @@ class TestLayerDetailsPage(SeleniumTestCase):
211 self.get(self.url) 193 self.get(self.url)
212 194
213 # Add the layer 195 # Add the layer
196 self.wait_until_clickable("#add-remove-layer-btn")
214 self.click("#add-remove-layer-btn") 197 self.click("#add-remove-layer-btn")
215 198
216 notification = self.wait_until_visible("#change-notification-msg") 199 notification = self.wait_until_visible("#change-notification-msg")
@@ -218,12 +201,17 @@ class TestLayerDetailsPage(SeleniumTestCase):
218 expected_text = "You have added 1 layer to your project: %s" % \ 201 expected_text = "You have added 1 layer to your project: %s" % \
219 self.imported_layer_version.layer.name 202 self.imported_layer_version.layer.name
220 203
221 self.assertTrue(expected_text in notification.text, 204 self.assertIn(expected_text, notification.text,
222 "Expected notification text %s not found was " 205 "Expected notification text %s not found was "
223 " \"%s\" instead" % 206 " \"%s\" instead" %
224 (expected_text, notification.text)) 207 (expected_text, notification.text))
225 208
209 hide_button = self.find('#hide-alert')
210 hide_button.click()
211 self.wait_until_not_visible('#change-notification')
212
226 # Remove the layer 213 # Remove the layer
214 self.wait_until_clickable("#add-remove-layer-btn")
227 self.click("#add-remove-layer-btn") 215 self.click("#add-remove-layer-btn")
228 216
229 notification = self.wait_until_visible("#change-notification-msg") 217 notification = self.wait_until_visible("#change-notification-msg")
@@ -231,7 +219,7 @@ class TestLayerDetailsPage(SeleniumTestCase):
231 expected_text = "You have removed 1 layer from your project: %s" % \ 219 expected_text = "You have removed 1 layer from your project: %s" % \
232 self.imported_layer_version.layer.name 220 self.imported_layer_version.layer.name
233 221
234 self.assertTrue(expected_text in notification.text, 222 self.assertIn(expected_text, notification.text,
235 "Expected notification text %s not found was " 223 "Expected notification text %s not found was "
236 " \"%s\" instead" % 224 " \"%s\" instead" %
237 (expected_text, notification.text)) 225 (expected_text, notification.text))
diff --git a/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py b/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py
index 9f0b6397fe..bf0304dbec 100644
--- a/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py
@@ -90,7 +90,7 @@ class TestNewCustomImagePage(SeleniumTestCase):
90 """ 90 """
91 url = reverse('newcustomimage', args=(self.project.id,)) 91 url = reverse('newcustomimage', args=(self.project.id,))
92 self.get(url) 92 self.get(url)
93 self.wait_until_visible('#global-nav', poll=3) 93 self.wait_until_visible('#global-nav')
94 94
95 self.click('button[data-recipe="%s"]' % self.recipe.id) 95 self.click('button[data-recipe="%s"]' % self.recipe.id)
96 96
diff --git a/bitbake/lib/toaster/tests/browser/test_new_project_page.py b/bitbake/lib/toaster/tests/browser/test_new_project_page.py
index 458bb6538d..e50f236c32 100644
--- a/bitbake/lib/toaster/tests/browser/test_new_project_page.py
+++ b/bitbake/lib/toaster/tests/browser/test_new_project_page.py
@@ -47,7 +47,7 @@ class TestNewProjectPage(SeleniumTestCase):
47 47
48 url = reverse('newproject') 48 url = reverse('newproject')
49 self.get(url) 49 self.get(url)
50 self.wait_until_visible('#new-project-name', poll=3) 50 self.wait_until_visible('#new-project-name')
51 self.enter_text('#new-project-name', project_name) 51 self.enter_text('#new-project-name', project_name)
52 52
53 select = Select(self.find('#projectversion')) 53 select = Select(self.find('#projectversion'))
@@ -58,7 +58,7 @@ class TestNewProjectPage(SeleniumTestCase):
58 # We should get redirected to the new project's page with the 58 # We should get redirected to the new project's page with the
59 # notification at the top 59 # notification at the top
60 element = self.wait_until_visible( 60 element = self.wait_until_visible(
61 '#project-created-notification', poll=3) 61 '#project-created-notification')
62 62
63 self.assertTrue(project_name in element.text, 63 self.assertTrue(project_name in element.text,
64 "New project name not in new project notification") 64 "New project name not in new project notification")
@@ -79,7 +79,7 @@ class TestNewProjectPage(SeleniumTestCase):
79 79
80 url = reverse('newproject') 80 url = reverse('newproject')
81 self.get(url) 81 self.get(url)
82 self.wait_until_visible('#new-project-name', poll=3) 82 self.wait_until_visible('#new-project-name')
83 83
84 self.enter_text('#new-project-name', project_name) 84 self.enter_text('#new-project-name', project_name)
85 85
@@ -89,12 +89,10 @@ class TestNewProjectPage(SeleniumTestCase):
89 radio = self.driver.find_element(By.ID, 'type-new') 89 radio = self.driver.find_element(By.ID, 'type-new')
90 radio.click() 90 radio.click()
91 91
92 self.click("#create-project-button") 92 self.wait_until_visible('#hint-error-project-name')
93
94 self.wait_until_present('#hint-error-project-name', poll=3)
95 element = self.find('#hint-error-project-name') 93 element = self.find('#hint-error-project-name')
96 94
97 self.assertTrue(("Project names must be unique" in element.text), 95 self.assertIn("Project names must be unique", element.text,
98 "Did not find unique project name error message") 96 "Did not find unique project name error message")
99 97
100 # Try and click it anyway, if it submits we'll have a new project in 98 # Try and click it anyway, if it submits we'll have a new project in