diff options
Diffstat (limited to 'bitbake/lib/toaster/tests/browser/test_all_builds_page.py')
-rw-r--r-- | bitbake/lib/toaster/tests/browser/test_all_builds_page.py | 315 |
1 files changed, 285 insertions, 30 deletions
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 8423d3dab2..b9356a0344 100644 --- a/bitbake/lib/toaster/tests/browser/test_all_builds_page.py +++ b/bitbake/lib/toaster/tests/browser/test_all_builds_page.py | |||
@@ -7,13 +7,18 @@ | |||
7 | # SPDX-License-Identifier: GPL-2.0-only | 7 | # SPDX-License-Identifier: GPL-2.0-only |
8 | # | 8 | # |
9 | 9 | ||
10 | import os | ||
10 | import re | 11 | import re |
11 | 12 | ||
12 | from django.urls import reverse | 13 | from django.urls import reverse |
14 | from selenium.webdriver.support.select import Select | ||
13 | from django.utils import timezone | 15 | from django.utils import timezone |
16 | from bldcontrol.models import BuildRequest | ||
14 | from tests.browser.selenium_helpers import SeleniumTestCase | 17 | from tests.browser.selenium_helpers import SeleniumTestCase |
15 | 18 | ||
16 | from orm.models import BitbakeVersion, Release, Project, Build, Target | 19 | from orm.models import BitbakeVersion, Layer, Layer_Version, Recipe, Release, Project, Build, Target, Task |
20 | |||
21 | from selenium.webdriver.common.by import By | ||
17 | 22 | ||
18 | 23 | ||
19 | class TestAllBuildsPage(SeleniumTestCase): | 24 | class TestAllBuildsPage(SeleniumTestCase): |
@@ -23,7 +28,8 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
23 | CLI_BUILDS_PROJECT_NAME = 'command line builds' | 28 | CLI_BUILDS_PROJECT_NAME = 'command line builds' |
24 | 29 | ||
25 | def setUp(self): | 30 | def setUp(self): |
26 | bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/', | 31 | builldir = os.environ.get('BUILDDIR', './') |
32 | bbv = BitbakeVersion.objects.create(name='bbv1', giturl=f'{builldir}/', | ||
27 | branch='master', dirpath='') | 33 | branch='master', dirpath='') |
28 | release = Release.objects.create(name='release1', | 34 | release = Release.objects.create(name='release1', |
29 | bitbake_version=bbv) | 35 | bitbake_version=bbv) |
@@ -69,7 +75,7 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
69 | '[data-role="data-recent-build-buildtime-field"]' % build.id | 75 | '[data-role="data-recent-build-buildtime-field"]' % build.id |
70 | 76 | ||
71 | # because this loads via Ajax, wait for it to be visible | 77 | # because this loads via Ajax, wait for it to be visible |
72 | self.wait_until_present(selector) | 78 | self.wait_until_visible(selector) |
73 | 79 | ||
74 | build_time_spans = self.find_all(selector) | 80 | build_time_spans = self.find_all(selector) |
75 | 81 | ||
@@ -79,7 +85,7 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
79 | 85 | ||
80 | def _get_row_for_build(self, build): | 86 | def _get_row_for_build(self, build): |
81 | """ Get the table row for the build from the all builds table """ | 87 | """ Get the table row for the build from the all builds table """ |
82 | self.wait_until_present('#allbuildstable') | 88 | self.wait_until_visible('#allbuildstable') |
83 | 89 | ||
84 | rows = self.find_all('#allbuildstable tr') | 90 | rows = self.find_all('#allbuildstable tr') |
85 | 91 | ||
@@ -91,7 +97,7 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
91 | found_row = None | 97 | found_row = None |
92 | for row in rows: | 98 | for row in rows: |
93 | 99 | ||
94 | outcome_links = row.find_elements_by_css_selector(selector) | 100 | outcome_links = row.find_elements(By.CSS_SELECTOR, selector) |
95 | if len(outcome_links) == 1: | 101 | if len(outcome_links) == 1: |
96 | found_row = row | 102 | found_row = row |
97 | break | 103 | break |
@@ -100,6 +106,66 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
100 | 106 | ||
101 | return found_row | 107 | return found_row |
102 | 108 | ||
109 | def _get_create_builds(self, **kwargs): | ||
110 | """ Create a build and return the build object """ | ||
111 | build1 = Build.objects.create(**self.project1_build_success) | ||
112 | build2 = Build.objects.create(**self.project1_build_failure) | ||
113 | |||
114 | # add some targets to these builds so they have recipe links | ||
115 | # (and so we can find the row in the ToasterTable corresponding to | ||
116 | # a particular build) | ||
117 | Target.objects.create(build=build1, target='foo') | ||
118 | Target.objects.create(build=build2, target='bar') | ||
119 | |||
120 | if kwargs: | ||
121 | # Create kwargs.get('success') builds with success status with target | ||
122 | # and kwargs.get('failure') builds with failure status with target | ||
123 | for i in range(kwargs.get('success', 0)): | ||
124 | now = timezone.now() | ||
125 | self.project1_build_success['started_on'] = now | ||
126 | self.project1_build_success[ | ||
127 | 'completed_on'] = now - timezone.timedelta(days=i) | ||
128 | build = Build.objects.create(**self.project1_build_success) | ||
129 | Target.objects.create(build=build, | ||
130 | target=f'{i}_success_recipe', | ||
131 | task=f'{i}_success_task') | ||
132 | |||
133 | self._set_buildRequest_and_task_on_build(build) | ||
134 | for i in range(kwargs.get('failure', 0)): | ||
135 | now = timezone.now() | ||
136 | self.project1_build_failure['started_on'] = now | ||
137 | self.project1_build_failure[ | ||
138 | 'completed_on'] = now - timezone.timedelta(days=i) | ||
139 | build = Build.objects.create(**self.project1_build_failure) | ||
140 | Target.objects.create(build=build, | ||
141 | target=f'{i}_fail_recipe', | ||
142 | task=f'{i}_fail_task') | ||
143 | self._set_buildRequest_and_task_on_build(build) | ||
144 | return build1, build2 | ||
145 | |||
146 | def _create_recipe(self): | ||
147 | """ Add a recipe to the database and return it """ | ||
148 | layer = Layer.objects.create() | ||
149 | layer_version = Layer_Version.objects.create(layer=layer) | ||
150 | return Recipe.objects.create(name='recipe_foo', layer_version=layer_version) | ||
151 | |||
152 | def _set_buildRequest_and_task_on_build(self, build): | ||
153 | """ Set buildRequest and task on build """ | ||
154 | build.recipes_parsed = 1 | ||
155 | build.save() | ||
156 | buildRequest = BuildRequest.objects.create( | ||
157 | build=build, | ||
158 | project=self.project1, | ||
159 | state=BuildRequest.REQ_COMPLETED) | ||
160 | build.build_request = buildRequest | ||
161 | recipe = self._create_recipe() | ||
162 | task = Task.objects.create(build=build, | ||
163 | recipe=recipe, | ||
164 | task_name='task', | ||
165 | outcome=Task.OUTCOME_SUCCESS) | ||
166 | task.save() | ||
167 | build.save() | ||
168 | |||
103 | def test_show_tasks_with_suffix(self): | 169 | def test_show_tasks_with_suffix(self): |
104 | """ Task should be shown as suffix on build name """ | 170 | """ Task should be shown as suffix on build name """ |
105 | build = Build.objects.create(**self.project1_build_success) | 171 | build = Build.objects.create(**self.project1_build_success) |
@@ -109,7 +175,7 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
109 | 175 | ||
110 | url = reverse('all-builds') | 176 | url = reverse('all-builds') |
111 | self.get(url) | 177 | self.get(url) |
112 | self.wait_until_present('td[class="target"]') | 178 | self.wait_until_visible('td[class="target"]') |
113 | 179 | ||
114 | cell = self.find('td[class="target"]') | 180 | cell = self.find('td[class="target"]') |
115 | content = cell.get_attribute('innerHTML') | 181 | content = cell.get_attribute('innerHTML') |
@@ -126,23 +192,25 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
126 | but should be shown for other builds | 192 | but should be shown for other builds |
127 | """ | 193 | """ |
128 | build1 = Build.objects.create(**self.project1_build_success) | 194 | build1 = Build.objects.create(**self.project1_build_success) |
129 | default_build = Build.objects.create(**self.default_project_build_success) | 195 | default_build = Build.objects.create( |
196 | **self.default_project_build_success) | ||
130 | 197 | ||
131 | url = reverse('all-builds') | 198 | url = reverse('all-builds') |
132 | self.get(url) | 199 | self.get(url) |
133 | 200 | ||
134 | # shouldn't see a rebuild button for command-line builds | ||
135 | selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % default_build.id | ||
136 | run_again_button = self.find_all(selector) | ||
137 | self.assertEqual(len(run_again_button), 0, | ||
138 | 'should not see a rebuild button for cli builds') | ||
139 | |||
140 | # 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') | ||
141 | selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id | 203 | selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % build1.id |
142 | run_again_button = self.find_all(selector) | 204 | run_again_button = self.find_all(selector) |
143 | self.assertEqual(len(run_again_button), 1, | 205 | self.assertEqual(len(run_again_button), 1, |
144 | 'should see a rebuild button for non-cli builds') | 206 | 'should see a rebuild button for non-cli builds') |
145 | 207 | ||
208 | # shouldn't see a rebuild button for command-line builds | ||
209 | selector = 'div[data-latest-build-result="%s"] .rebuild-btn' % default_build.id | ||
210 | run_again_button = self.find_all(selector) | ||
211 | self.assertEqual(len(run_again_button), 0, | ||
212 | 'should not see a rebuild button for cli builds') | ||
213 | |||
146 | def test_tooltips_on_project_name(self): | 214 | def test_tooltips_on_project_name(self): |
147 | """ | 215 | """ |
148 | Test tooltips shown next to project name in the main table | 216 | Test tooltips shown next to project name in the main table |
@@ -156,6 +224,7 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
156 | 224 | ||
157 | url = reverse('all-builds') | 225 | url = reverse('all-builds') |
158 | self.get(url) | 226 | self.get(url) |
227 | self.wait_until_visible('#allbuildstable', poll=3) | ||
159 | 228 | ||
160 | # get the project name cells from the table | 229 | # get the project name cells from the table |
161 | cells = self.find_all('#allbuildstable td[class="project"]') | 230 | cells = self.find_all('#allbuildstable td[class="project"]') |
@@ -164,7 +233,7 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
164 | 233 | ||
165 | for cell in cells: | 234 | for cell in cells: |
166 | content = cell.get_attribute('innerHTML') | 235 | content = cell.get_attribute('innerHTML') |
167 | help_icons = cell.find_elements_by_css_selector(selector) | 236 | help_icons = cell.find_elements(By.CSS_SELECTOR, selector) |
168 | 237 | ||
169 | if re.search(self.PROJECT_NAME, content): | 238 | if re.search(self.PROJECT_NAME, content): |
170 | # no help icon next to non-cli project name | 239 | # no help icon next to non-cli project name |
@@ -184,38 +253,224 @@ class TestAllBuildsPage(SeleniumTestCase): | |||
184 | recent builds area; failed builds should not have links on the time column, | 253 | recent builds area; failed builds should not have links on the time column, |
185 | or in the recent builds area | 254 | or in the recent builds area |
186 | """ | 255 | """ |
187 | build1 = Build.objects.create(**self.project1_build_success) | 256 | build1, build2 = self._get_create_builds() |
188 | build2 = Build.objects.create(**self.project1_build_failure) | ||
189 | |||
190 | # add some targets to these builds so they have recipe links | ||
191 | # (and so we can find the row in the ToasterTable corresponding to | ||
192 | # a particular build) | ||
193 | Target.objects.create(build=build1, target='foo') | ||
194 | Target.objects.create(build=build2, target='bar') | ||
195 | 257 | ||
196 | url = reverse('all-builds') | 258 | url = reverse('all-builds') |
197 | self.get(url) | 259 | self.get(url) |
260 | self.wait_until_visible('#allbuildstable', poll=3) | ||
198 | 261 | ||
199 | # test recent builds area for successful build | 262 | # test recent builds area for successful build |
200 | element = self._get_build_time_element(build1) | 263 | element = self._get_build_time_element(build1) |
201 | links = element.find_elements_by_css_selector('a') | 264 | links = element.find_elements(By.CSS_SELECTOR, 'a') |
202 | msg = 'should be a link on the build time for a successful recent build' | 265 | msg = 'should be a link on the build time for a successful recent build' |
203 | self.assertEquals(len(links), 1, msg) | 266 | self.assertEqual(len(links), 1, msg) |
204 | 267 | ||
205 | # test recent builds area for failed build | 268 | # test recent builds area for failed build |
206 | element = self._get_build_time_element(build2) | 269 | element = self._get_build_time_element(build2) |
207 | links = element.find_elements_by_css_selector('a') | 270 | links = element.find_elements(By.CSS_SELECTOR, 'a') |
208 | msg = 'should not be a link on the build time for a failed recent build' | 271 | msg = 'should not be a link on the build time for a failed recent build' |
209 | self.assertEquals(len(links), 0, msg) | 272 | self.assertEqual(len(links), 0, msg) |
210 | 273 | ||
211 | # test the time column for successful build | 274 | # test the time column for successful build |
212 | build1_row = self._get_row_for_build(build1) | 275 | build1_row = self._get_row_for_build(build1) |
213 | links = build1_row.find_elements_by_css_selector('td.time a') | 276 | links = build1_row.find_elements(By.CSS_SELECTOR, 'td.time a') |
214 | msg = 'should be a link on the build time for a successful build' | 277 | msg = 'should be a link on the build time for a successful build' |
215 | self.assertEquals(len(links), 1, msg) | 278 | self.assertEqual(len(links), 1, msg) |
216 | 279 | ||
217 | # test the time column for failed build | 280 | # test the time column for failed build |
218 | build2_row = self._get_row_for_build(build2) | 281 | build2_row = self._get_row_for_build(build2) |
219 | links = build2_row.find_elements_by_css_selector('td.time a') | 282 | links = build2_row.find_elements(By.CSS_SELECTOR, 'td.time a') |
220 | msg = 'should not be a link on the build time for a failed build' | 283 | msg = 'should not be a link on the build time for a failed build' |
221 | self.assertEquals(len(links), 0, msg) | 284 | self.assertEqual(len(links), 0, msg) |
285 | |||
286 | def test_builds_table_search_box(self): | ||
287 | """ Test the search box in the builds table on the all builds page """ | ||
288 | self._get_create_builds() | ||
289 | |||
290 | url = reverse('all-builds') | ||
291 | self.get(url) | ||
292 | |||
293 | # Check search box is present and works | ||
294 | self.wait_until_visible('#allbuildstable tbody tr') | ||
295 | search_box = self.find('#search-input-allbuildstable') | ||
296 | self.assertTrue(search_box.is_displayed()) | ||
297 | |||
298 | # Check that we can search for a build by recipe name | ||
299 | search_box.send_keys('foo') | ||
300 | search_btn = self.find('#search-submit-allbuildstable') | ||
301 | search_btn.click() | ||
302 | self.wait_until_visible('#allbuildstable tbody tr') | ||
303 | rows = self.find_all('#allbuildstable tbody tr') | ||
304 | self.assertTrue(len(rows) >= 1) | ||
305 | |||
306 | def test_filtering_on_failure_tasks_column(self): | ||
307 | """ Test the filtering on failure tasks column in the builds table on the all builds page """ | ||
308 | def _check_if_filter_failed_tasks_column_is_visible(): | ||
309 | # check if failed tasks filter column is visible, if not click on it | ||
310 | # Check edit column | ||
311 | edit_column = self.find('#edit-columns-button') | ||
312 | self.assertTrue(edit_column.is_displayed()) | ||
313 | edit_column.click() | ||
314 | # Check dropdown is visible | ||
315 | self.wait_until_visible('ul.dropdown-menu.editcol') | ||
316 | filter_fails_task_checkbox = self.find('#checkbox-failed_tasks') | ||
317 | if not filter_fails_task_checkbox.is_selected(): | ||
318 | filter_fails_task_checkbox.click() | ||
319 | edit_column.click() | ||
320 | |||
321 | self._get_create_builds(success=10, failure=10) | ||
322 | |||
323 | url = reverse('all-builds') | ||
324 | self.get(url) | ||
325 | |||
326 | # Check filtering on failure tasks column | ||
327 | self.wait_until_visible('#allbuildstable tbody tr') | ||
328 | _check_if_filter_failed_tasks_column_is_visible() | ||
329 | failed_tasks_filter = self.find('#failed_tasks_filter') | ||
330 | failed_tasks_filter.click() | ||
331 | # Check popup is visible | ||
332 | self.wait_until_visible('#filter-modal-allbuildstable') | ||
333 | self.assertTrue( | ||
334 | self.find('#filter-modal-allbuildstable').is_displayed()) | ||
335 | # Check that we can filter by failure tasks | ||
336 | build_without_failure_tasks = self.find( | ||
337 | '#failed_tasks_filter\\:without_failed_tasks') | ||
338 | build_without_failure_tasks.click() | ||
339 | # click on apply button | ||
340 | self.find('#filter-modal-allbuildstable .btn-primary').click() | ||
341 | self.wait_until_visible('#allbuildstable tbody tr') | ||
342 | # Check if filter is applied, by checking if failed_tasks_filter has btn-primary class | ||
343 | self.assertTrue(self.find('#failed_tasks_filter').get_attribute( | ||
344 | 'class').find('btn-primary') != -1) | ||
345 | |||
346 | def test_filtering_on_completedOn_column(self): | ||
347 | """ Test the filtering on completed_on column in the builds table on the all builds page """ | ||
348 | self._get_create_builds(success=10, failure=10) | ||
349 | |||
350 | url = reverse('all-builds') | ||
351 | self.get(url) | ||
352 | |||
353 | # Check filtering on failure tasks column | ||
354 | self.wait_until_visible('#allbuildstable tbody tr') | ||
355 | completed_on_filter = self.find('#completed_on_filter') | ||
356 | completed_on_filter.click() | ||
357 | # Check popup is visible | ||
358 | self.wait_until_visible('#filter-modal-allbuildstable') | ||
359 | self.assertTrue( | ||
360 | self.find('#filter-modal-allbuildstable').is_displayed()) | ||
361 | # Check that we can filter by failure tasks | ||
362 | build_without_failure_tasks = self.find( | ||
363 | '#completed_on_filter\\:date_range') | ||
364 | build_without_failure_tasks.click() | ||
365 | # click on apply button | ||
366 | self.find('#filter-modal-allbuildstable .btn-primary').click() | ||
367 | self.wait_until_visible('#allbuildstable tbody tr') | ||
368 | # Check if filter is applied, by checking if completed_on_filter has btn-primary class | ||
369 | self.assertTrue(self.find('#completed_on_filter').get_attribute( | ||
370 | 'class').find('btn-primary') != -1) | ||
371 | |||
372 | # Filter by date range | ||
373 | self.find('#completed_on_filter').click() | ||
374 | self.wait_until_visible('#filter-modal-allbuildstable') | ||
375 | date_ranges = self.driver.find_elements( | ||
376 | By.XPATH, '//input[@class="form-control hasDatepicker"]') | ||
377 | today = timezone.now() | ||
378 | yestersday = today - timezone.timedelta(days=1) | ||
379 | date_ranges[0].send_keys(yestersday.strftime('%Y-%m-%d')) | ||
380 | date_ranges[1].send_keys(today.strftime('%Y-%m-%d')) | ||
381 | self.find('#filter-modal-allbuildstable .btn-primary').click() | ||
382 | self.wait_until_visible('#allbuildstable tbody tr') | ||
383 | self.assertTrue(self.find('#completed_on_filter').get_attribute( | ||
384 | 'class').find('btn-primary') != -1) | ||
385 | # Check if filter is applied, number of builds displayed should be 6 | ||
386 | self.assertTrue(len(self.find_all('#allbuildstable tbody tr')) >= 4) | ||
387 | |||
388 | def test_builds_table_editColumn(self): | ||
389 | """ Test the edit column feature in the builds table on the all builds page """ | ||
390 | self._get_create_builds(success=10, failure=10) | ||
391 | |||
392 | def test_edit_column(check_box_id): | ||
393 | # Check that we can hide/show table column | ||
394 | check_box = self.find(f'#{check_box_id}') | ||
395 | th_class = str(check_box_id).replace('checkbox-', '') | ||
396 | if check_box.is_selected(): | ||
397 | # check if column is visible in table | ||
398 | self.assertTrue( | ||
399 | self.find( | ||
400 | f'#allbuildstable thead th.{th_class}' | ||
401 | ).is_displayed(), | ||
402 | f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table" | ||
403 | ) | ||
404 | check_box.click() | ||
405 | # check if column is hidden in table | ||
406 | self.assertFalse( | ||
407 | self.find( | ||
408 | f'#allbuildstable thead th.{th_class}' | ||
409 | ).is_displayed(), | ||
410 | f"The {th_class} column is unchecked in EditColumn dropdown, but it's visible in table" | ||
411 | ) | ||
412 | else: | ||
413 | # check if column is hidden in table | ||
414 | self.assertFalse( | ||
415 | self.find( | ||
416 | f'#allbuildstable thead th.{th_class}' | ||
417 | ).is_displayed(), | ||
418 | f"The {th_class} column is unchecked in EditColumn dropdown, but it's visible in table" | ||
419 | ) | ||
420 | check_box.click() | ||
421 | # check if column is visible in table | ||
422 | self.assertTrue( | ||
423 | self.find( | ||
424 | f'#allbuildstable thead th.{th_class}' | ||
425 | ).is_displayed(), | ||
426 | f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table" | ||
427 | ) | ||
428 | url = reverse('all-builds') | ||
429 | self.get(url) | ||
430 | self.wait_until_visible('#allbuildstable tbody tr') | ||
431 | |||
432 | # Check edit column | ||
433 | edit_column = self.find('#edit-columns-button') | ||
434 | self.assertTrue(edit_column.is_displayed()) | ||
435 | edit_column.click() | ||
436 | # Check dropdown is visible | ||
437 | self.wait_until_visible('ul.dropdown-menu.editcol') | ||
438 | |||
439 | # Check that we can hide the edit column | ||
440 | test_edit_column('checkbox-errors_no') | ||
441 | test_edit_column('checkbox-failed_tasks') | ||
442 | test_edit_column('checkbox-image_files') | ||
443 | test_edit_column('checkbox-project') | ||
444 | test_edit_column('checkbox-started_on') | ||
445 | test_edit_column('checkbox-time') | ||
446 | test_edit_column('checkbox-warnings_no') | ||
447 | |||
448 | def test_builds_table_show_rows(self): | ||
449 | """ Test the show rows feature in the builds table on the all builds page """ | ||
450 | self._get_create_builds(success=100, failure=100) | ||
451 | |||
452 | def test_show_rows(row_to_show, show_row_link): | ||
453 | # Check that we can show rows == row_to_show | ||
454 | show_row_link.select_by_value(str(row_to_show)) | ||
455 | self.wait_until_visible('#allbuildstable tbody tr', poll=3) | ||
456 | # check at least some rows are visible | ||
457 | self.assertTrue( | ||
458 | len(self.find_all('#allbuildstable tbody tr')) > 0 | ||
459 | ) | ||
460 | |||
461 | url = reverse('all-builds') | ||
462 | self.get(url) | ||
463 | self.wait_until_visible('#allbuildstable tbody tr') | ||
464 | |||
465 | show_rows = self.driver.find_elements( | ||
466 | By.XPATH, | ||
467 | '//select[@class="form-control pagesize-allbuildstable"]' | ||
468 | ) | ||
469 | # Check show rows | ||
470 | for show_row_link in show_rows: | ||
471 | show_row_link = Select(show_row_link) | ||
472 | test_show_rows(10, show_row_link) | ||
473 | test_show_rows(25, show_row_link) | ||
474 | test_show_rows(50, show_row_link) | ||
475 | test_show_rows(100, show_row_link) | ||
476 | test_show_rows(150, show_row_link) | ||