* [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation:
@ 2023-11-21 13:50 Alassane Yattara
2023-11-21 13:50 ` [PATCH 2/7] Toaster: Write UI TestCase -> Test project config tab Alassane Yattara
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
- Check if the menu is displayed and contains the right elements:
- Configuration
- COMPATIBLE METADATA
- Custom images
- Image recipes
- Software recipes
- Machines
- Layers
- Distro
- EXTRA CONFIGURATION
- Bitbake variables
- Actions
- Delete project
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 176 ++++++++++++++++++
1 file changed, 176 insertions(+)
create mode 100644 lib/toaster/tests/functional/test_project_page_tab_config.py
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
new file mode 100644
index 00000000..f0c6aacf
--- /dev/null
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -0,0 +1,176 @@
+#! /usr/bin/env python3 #
+# BitBake Toaster UI tests implementation
+#
+# Copyright (C) 2023 Savoir-faire Linux
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+from time import sleep
+import pytest
+from django.urls import reverse
+from selenium.webdriver.support.select import Select
+from selenium.common.exceptions import NoSuchElementException
+from tests.functional.functional_helpers import SeleniumFunctionalTestCase
+from selenium.webdriver.common.by import By
+
+
+@pytest.mark.django_db
+class TestProjectConfigTab(SeleniumFunctionalTestCase):
+
+ def setUp(self):
+ self.recipe = None
+ super().setUp()
+ release = '3'
+ project_name = 'projectmaster'
+ self._create_test_new_project(
+ project_name,
+ release,
+ False,
+ )
+
+ def _create_test_new_project(
+ self,
+ project_name,
+ release,
+ merge_toaster_settings,
+ ):
+ """ Create/Test new project using:
+ - Project Name: Any string
+ - Release: Any string
+ - Merge Toaster settings: True or False
+ """
+ self.get(reverse('newproject'))
+ self.driver.find_element(By.ID,
+ "new-project-name").send_keys(project_name)
+
+ select = Select(self.find('#projectversion'))
+ select.select_by_value(release)
+
+ # check merge toaster settings
+ checkbox = self.find('.checkbox-mergeattr')
+ if merge_toaster_settings:
+ if not checkbox.is_selected():
+ checkbox.click()
+ else:
+ if checkbox.is_selected():
+ checkbox.click()
+
+ self.driver.find_element(By.ID, "create-project-button").click()
+
+ @classmethod
+ def _wait_until_build(cls, state):
+ while True:
+ try:
+ last_build_state = cls.driver.find_element(
+ By.XPATH,
+ '//*[@id="latest-builds"]/div[1]//div[@class="build-state"]',
+ )
+ build_state = last_build_state.get_attribute(
+ 'data-build-state')
+ state_text = state.lower().split()
+ if any(x in str(build_state).lower() for x in state_text):
+ break
+ except NoSuchElementException:
+ continue
+ sleep(1)
+
+ def _create_builds(self):
+ # check search box can be use to build recipes
+ search_box = self.find('#build-input')
+ search_box.send_keys('core-image-minimal')
+ self.find('#build-button').click()
+ sleep(1)
+ self.wait_until_visible('#latest-builds')
+ # loop until reach the parsing state
+ self._wait_until_build('parsing starting cloning')
+ lastest_builds = self.driver.find_elements(
+ By.XPATH,
+ '//div[@id="latest-builds"]/div',
+ )
+ last_build = lastest_builds[0]
+ self.assertTrue(
+ 'core-image-minimal' in str(last_build.text)
+ )
+ cancel_button = last_build.find_element(
+ By.XPATH,
+ '//span[@class="cancel-build-btn pull-right alert-link"]',
+ )
+ cancel_button.click()
+ sleep(1)
+ self._wait_until_build('cancelled')
+
+ def _get_tabs(self):
+ # tabs links list
+ return self.driver.find_elements(
+ By.XPATH,
+ '//div[@id="project-topbar"]//li'
+ )
+
+ def _get_config_nav_item(self, index):
+ config_nav = self.find('#config-nav')
+ return config_nav.find_elements(By.TAG_NAME, 'li')[index]
+
+ def test_project_config_nav(self):
+ """ Test project config tab navigation:
+ - Check if the menu is displayed and contains the right elements:
+ - Configuration
+ - COMPATIBLE METADATA
+ - Custom images
+ - Image recipes
+ - Software recipes
+ - Machines
+ - Layers
+ - Distro
+ - EXTRA CONFIGURATION
+ - Bitbake variables
+ - Actions
+ - Delete project
+ """
+ # navigate to the project page
+ url = reverse("project", args=(1,))
+ self.get(url)
+
+ # check if the menu is displayed
+ self.wait_until_visible('#config-nav')
+
+ def _get_config_nav_item(index):
+ config_nav = self.find('#config-nav')
+ return config_nav.find_elements(By.TAG_NAME, 'li')[index]
+
+ def check_config_nav_item(index, item_name, url):
+ item = _get_config_nav_item(index)
+ self.assertTrue(item_name in item.text)
+ self.assertTrue(item.get_attribute('class') == 'active')
+ self.assertTrue(url in self.driver.current_url)
+
+ # check if the menu contains the right elements
+ # COMPATIBLE METADATA
+ compatible_metadata = _get_config_nav_item(1)
+ self.assertTrue(
+ "compatible metadata" in compatible_metadata.text.lower()
+ )
+ # EXTRA CONFIGURATION
+ extra_configuration = _get_config_nav_item(8)
+ self.assertTrue(
+ "extra configuration" in extra_configuration.text.lower()
+ )
+ # Actions
+ actions = _get_config_nav_item(10)
+ self.assertTrue("actions" in str(actions.text).lower())
+
+ conf_nav_list = [
+ [0, 'Configuration', f"/toastergui/project/1"], # config
+ [2, 'Custom images', f"/toastergui/project/1/customimages"], # custom images
+ [3, 'Image recipes', f"/toastergui/project/1/images"], # image recipes
+ [4, 'Software recipes', f"/toastergui/project/1/softwarerecipes"], # software recipes
+ [5, 'Machines', f"/toastergui/project/1/machines"], # machines
+ [6, 'Layers', f"/toastergui/project/1/layers"], # layers
+ [7, 'Distro', f"/toastergui/project/1/distro"], # distro
+ [9, 'BitBake variables', f"/toastergui/project/1/configuration"], # bitbake variables
+ ]
+ for index, item_name, url in conf_nav_list:
+ item = _get_config_nav_item(index)
+ if item.get_attribute('class') != 'active':
+ item.click()
+ check_config_nav_item(index, item_name, url)
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/7] Toaster: Write UI TestCase -> Test project config tab
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
@ 2023-11-21 13:50 ` Alassane Yattara
2023-11-21 13:50 ` [PATCH 3/7] Toaster: Write UI TestCase -> Test project page tab import layer Alassane Yattara
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
Check if project config tab right section contains five blocks:
- Machine:
- check 'Machine' is displayed
- check can change Machine
- Distro:
- check 'Distro' is displayed
- check can change Distro
- Most built recipes:
- check 'Most built recipes' is displayed
- check can select a recipe and build it
- Project release:
- check 'Project release' is displayed
- check project has right release displayed
- Layers:
- check can add a layer if exists
- check at least three layers are displayed
- openembedded-core
- meta-poky
- meta-yocto-bsp
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 132 ++++++++++++++++++
.../toastergui/templates/mrb_section.html | 2 +-
2 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
index f0c6aacf..ca3b88d2 100644
--- a/lib/toaster/tests/functional/test_project_page_tab_config.py
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -9,6 +9,7 @@
from time import sleep
import pytest
from django.urls import reverse
+from selenium.webdriver import Keys
from selenium.webdriver.support.select import Select
from selenium.common.exceptions import NoSuchElementException
from tests.functional.functional_helpers import SeleniumFunctionalTestCase
@@ -174,3 +175,134 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
if item.get_attribute('class') != 'active':
item.click()
check_config_nav_item(index, item_name, url)
+
+ def test_project_config_tab_right_section(self):
+ """ Test project config tab right section contains five blocks:
+ - Machine:
+ - check 'Machine' is displayed
+ - check can change Machine
+ - Distro:
+ - check 'Distro' is displayed
+ - check can change Distro
+ - Most built recipes:
+ - check 'Most built recipes' is displayed
+ - check can select a recipe and build it
+ - Project release:
+ - check 'Project release' is displayed
+ - check project has right release displayed
+ - Layers:
+ - check can add a layer if exists
+ - check at least three layers are displayed
+ - openembedded-core
+ - meta-poky
+ - meta-yocto-bsp
+ """
+ # navigate to the project page
+ url = reverse("project", args=(1,))
+ self.get(url)
+
+ # check if the menu is displayed
+ self.wait_until_visible('#project-page')
+ block_l = self.driver.find_element(
+ By.XPATH, '//*[@id="project-page"]/div[2]')
+ machine = self.find('#machine-section')
+ distro = self.find('#distro-section')
+ most_built_recipes = self.driver.find_element(
+ By.XPATH, '//*[@id="project-page"]/div[1]/div[3]')
+ project_release = self.driver.find_element(
+ By.XPATH, '//*[@id="project-page"]/div[1]/div[4]')
+ layers = block_l.find_element(By.ID, 'layer-container')
+
+ def check_machine_distro(self, item_name, new_item_name, block):
+ title = block.find_element(By.TAG_NAME, 'h3')
+ self.assertTrue(item_name.capitalize() in title.text)
+ edit_btn = block.find_element(By.ID, f'change-{item_name}-toggle')
+ edit_btn.click()
+ sleep(1)
+ name_input = block.find_element(By.ID, f'{item_name}-change-input')
+ name_input.clear()
+ name_input.send_keys(new_item_name)
+ change_btn = block.find_element(By.ID, f'{item_name}-change-btn')
+ change_btn.click()
+ sleep(1)
+ project_name = block.find_element(By.ID, f'project-{item_name}-name')
+ self.assertTrue(new_item_name in project_name.text)
+ # check change notificaiton is displayed
+ change_notification = self.find('#change-notification')
+ self.assertTrue(
+ f'You have changed the {item_name} to: {new_item_name}' in change_notification.text
+ )
+
+ # Machine
+ check_machine_distro(self, 'machine', 'qemux86-64', machine)
+ # Distro
+ check_machine_distro(self, 'distro', 'poky-altcfg', distro)
+
+ # Project release
+ title = project_release.find_element(By.TAG_NAME, 'h3')
+ self.assertTrue("Project release" in title.text)
+ self.assertTrue(
+ "Yocto Project master" in self.find('#project-release-title').text
+ )
+
+ # Layers
+ title = layers.find_element(By.TAG_NAME, 'h3')
+ self.assertTrue("Layers" in title.text)
+ # check at least three layers are displayed
+ # openembedded-core
+ # meta-poky
+ # meta-yocto-bsp
+ layers_list = layers.find_element(By.ID, 'layers-in-project-list')
+ layers_list_items = layers_list.find_elements(By.TAG_NAME, 'li')
+ self.assertTrue(len(layers_list_items) == 3)
+ # check can add a layer if exists
+ add_layer_input = layers.find_element(By.ID, 'layer-add-input')
+ add_layer_input.send_keys('meta-oe')
+ self.wait_until_visible('#layer-container > form > div > span > div')
+ dropdown_item = self.driver.find_element(
+ By.XPATH,
+ '//*[@id="layer-container"]/form/div/span/div'
+ )
+ dropdown_item.click()
+ add_layer_btn = layers.find_element(By.ID, 'add-layer-btn')
+ add_layer_btn.click()
+ sleep(1)
+ # check layer is added
+ layers_list_items = layers_list.find_elements(By.TAG_NAME, 'li')
+ self.assertTrue(len(layers_list_items) == 4)
+
+ # Most built recipes
+ title = most_built_recipes.find_element(By.TAG_NAME, 'h3')
+ self.assertTrue("Most built recipes" in title.text)
+ # Create a new builds 5
+ self._create_builds()
+
+ # Refresh the page
+ self.get(url)
+
+ sleep(1) # wait for page to load
+ self.wait_until_visible('#project-page')
+ # check can select a recipe and build it
+ most_built_recipes = self.driver.find_element(
+ By.XPATH, '//*[@id="project-page"]/div[1]/div[3]')
+ recipe_list = most_built_recipes.find_element(By.ID, 'freq-build-list')
+ recipe_list_items = recipe_list.find_elements(By.TAG_NAME, 'li')
+ self.assertTrue(len(recipe_list_items) > 0)
+ checkbox = recipe_list_items[0].find_element(By.TAG_NAME, 'input')
+ checkbox.click()
+ build_btn = self.find('#freq-build-btn')
+ build_btn.click()
+ sleep(1) # wait for page to load
+ self.wait_until_visible('#latest-builds')
+ self._wait_until_build('parsing starting cloning queueing')
+ lastest_builds = self.driver.find_elements(
+ By.XPATH,
+ '//div[@id="latest-builds"]/div'
+ )
+ last_build = lastest_builds[0]
+ cancel_button = last_build.find_element(
+ By.XPATH,
+ '//span[@class="cancel-build-btn pull-right alert-link"]',
+ )
+ cancel_button.click()
+ self.assertTrue(len(lastest_builds) == 2)
diff --git a/lib/toaster/toastergui/templates/mrb_section.html b/lib/toaster/toastergui/templates/mrb_section.html
index 98d9fac8..9fc7dfae 100644
--- a/lib/toaster/toastergui/templates/mrb_section.html
+++ b/lib/toaster/toastergui/templates/mrb_section.html
@@ -63,7 +63,7 @@
<%/if%>
</div>
- <div data-build-state="<%:state%>">
+ <div class="build-state" data-build-state="<%:state%>">
<%if state == 'Cloning'%>
<%include tmpl='#cloning-repos-build-template'/%>
<%else state == 'Parsing'%>
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/7] Toaster: Write UI TestCase -> Test project page tab import layer
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
2023-11-21 13:50 ` [PATCH 2/7] Toaster: Write UI TestCase -> Test project config tab Alassane Yattara
@ 2023-11-21 13:50 ` Alassane Yattara
2023-11-21 13:50 ` [PATCH 4/7] Toaster: Write UI TestCase -> Test project page tab "New custom image" Alassane Yattara
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
index ca3b88d2..14a859a1 100644
--- a/lib/toaster/tests/functional/test_project_page_tab_config.py
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -306,3 +306,46 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
)
cancel_button.click()
self.assertTrue(len(lastest_builds) == 2)
+
+ def test_project_page_tab_importlayer(self):
+ """ Test project page tab import layer """
+ # navigate to the project page
+ url = reverse("project", args=(1,))
+ self.get(url)
+
+ # navigate to "Import layers" tab
+ import_layers_tab = self._get_tabs()[2]
+ import_layers_tab.find_element(By.TAG_NAME, 'a').click()
+ self.wait_until_visible('#layer-git-repo-url')
+
+ # Check git repo radio button
+ git_repo_radio = self.find('#git-repo-radio')
+ git_repo_radio.click()
+
+ # Set git repo url
+ input_repo_url = self.find('#layer-git-repo-url')
+ input_repo_url.send_keys('git://git.yoctoproject.org/meta-fake')
+ # Blur the input to trigger the validation
+ input_repo_url.send_keys(Keys.TAB)
+
+ # Check name is set
+ input_layer_name = self.find('#import-layer-name')
+ self.assertTrue(input_layer_name.get_attribute('value') == 'meta-fake')
+
+ # Set branch
+ input_branch = self.find('#layer-git-ref')
+ input_branch.send_keys('master')
+
+ # Import layer
+ self.find('#import-and-add-btn').click()
+
+ # Check layer is added
+ self.wait_until_visible('#layer-container')
+ block_l = self.driver.find_element(
+ By.XPATH, '//*[@id="project-page"]/div[2]')
+ layers = block_l.find_element(By.ID, 'layer-container')
+ layers_list = layers.find_element(By.ID, 'layers-in-project-list')
+ layers_list_items = layers_list.find_elements(By.TAG_NAME, 'li')
+ self.assertTrue(
+ 'meta-fake' in str(layers_list_items[-1].text)
+ )
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/7] Toaster: Write UI TestCase -> Test project page tab "New custom image"
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
2023-11-21 13:50 ` [PATCH 2/7] Toaster: Write UI TestCase -> Test project config tab Alassane Yattara
2023-11-21 13:50 ` [PATCH 3/7] Toaster: Write UI TestCase -> Test project page tab import layer Alassane Yattara
@ 2023-11-21 13:50 ` Alassane Yattara
2023-11-21 13:50 ` [PATCH 5/7] Toaster: Write UI TestCase -> Test project page section images Alassane Yattara
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
Test project page tab "New custom image" when no custom image
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
index 14a859a1..c6d952fd 100644
--- a/lib/toaster/tests/functional/test_project_page_tab_config.py
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -349,3 +349,34 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
self.assertTrue(
'meta-fake' in str(layers_list_items[-1].text)
)
+
+ def test_project_page_custom_image_no_image(self):
+ """ Test project page tab "New custom image" when no custom image """
+ # navigate to the project page
+ url = reverse("project", args=(1,))
+ self.get(url)
+
+ # navigate to "Custom image" tab
+ custom_image_section = self._get_config_nav_item(2)
+ custom_image_section.click()
+ self.wait_until_visible('#empty-state-customimagestable')
+
+ # Check message when no custom image
+ self.assertTrue(
+ "You have not created any custom images yet." in str(
+ self.find('#empty-state-customimagestable').text
+ )
+ )
+ div_empty_msg = self.find('#empty-state-customimagestable')
+ link_create_custom_image = div_empty_msg.find_element(
+ By.TAG_NAME, 'a')
+ self.assertTrue(
+ f"/toastergui/project/1/newcustomimage" in str(
+ link_create_custom_image.get_attribute('href')
+ )
+ )
+ self.assertTrue(
+ "Create your first custom image" in str(
+ link_create_custom_image.text
+ )
+ )
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/7] Toaster: Write UI TestCase -> Test project page section images
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
` (2 preceding siblings ...)
2023-11-21 13:50 ` [PATCH 4/7] Toaster: Write UI TestCase -> Test project page tab "New custom image" Alassane Yattara
@ 2023-11-21 13:50 ` Alassane Yattara
2023-11-21 13:50 ` [PATCH 6/7] Toaster: Write UI TestCase -> the edit column feature in image recipe Alassane Yattara
2023-11-21 13:50 ` [PATCH 7/7] Toaster: Write UI TestCase -> Test the show rows " Alassane Yattara
5 siblings, 0 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
BUILD IMAGE RECIPES: toastergui/project/{id}/images/
Test project page section images
- Check image recipes are displayed
- Check search input
- Check image recipe build button works
- Check image recipe table features(show/hide column, pagination)
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
index c6d952fd..598a8055 100644
--- a/lib/toaster/tests/functional/test_project_page_tab_config.py
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -380,3 +380,44 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
link_create_custom_image.text
)
)
+
+ def test_project_page_image_recipe(self):
+ """ Test project page section images
+ - Check image recipes are displayed
+ - Check search input
+ - Check image recipe build button works
+ - Check image recipe table features(show/hide column, pagination)
+ """
+ # navigate to the project page
+ url = reverse("project", args=(1,))
+ self.get(url)
+ self.wait_until_visible('#config-nav')
+
+ # navigate to "Images section"
+ images_section = self._get_config_nav_item(3)
+ images_section.click()
+ self.wait_until_visible('#imagerecipestable')
+ rows = self.find_all('#imagerecipestable tbody tr')
+ self.assertTrue(len(rows) > 0)
+
+ # Test search input
+ self.wait_until_visible('#search-input-imagerecipestable')
+ recipe_input = self.find('#search-input-imagerecipestable')
+ recipe_input.send_keys('core-image-minimal')
+ self.find('#search-submit-imagerecipestable').click()
+ rows = self.find_all('#imagerecipestable tbody tr')
+ self.assertTrue(len(rows) > 0)
+
+ # Test build button
+ image_to_build = rows[0]
+ build_btn = image_to_build.find_element(
+ By.XPATH,
+ '//td[@class="add-del-layers"]'
+ )
+ build_btn.click()
+ self._wait_until_build('parsing starting cloning')
+ lastest_builds = self.driver.find_elements(
+ By.XPATH,
+ '//div[@id="latest-builds"]/div'
+ )
+ self.assertTrue(len(lastest_builds) > 0)
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6/7] Toaster: Write UI TestCase -> the edit column feature in image recipe
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
` (3 preceding siblings ...)
2023-11-21 13:50 ` [PATCH 5/7] Toaster: Write UI TestCase -> Test project page section images Alassane Yattara
@ 2023-11-21 13:50 ` Alassane Yattara
2023-11-21 13:50 ` [PATCH 7/7] Toaster: Write UI TestCase -> Test the show rows " Alassane Yattara
5 siblings, 0 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
BUILD IMAGE RECIPES: toastergui/project/{id}/images/
Test the edit column feature in image recipe table on project page
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 121 ++++++++++++++++++
1 file changed, 121 insertions(+)
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
index 598a8055..2dfc120d 100644
--- a/lib/toaster/tests/functional/test_project_page_tab_config.py
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -8,10 +8,12 @@
from time import sleep
import pytest
+from django.utils import timezone
from django.urls import reverse
from selenium.webdriver import Keys
from selenium.webdriver.support.select import Select
from selenium.common.exceptions import NoSuchElementException
+from orm.models import Build, Project, Target
from tests.functional.functional_helpers import SeleniumFunctionalTestCase
from selenium.webdriver.common.by import By
@@ -112,6 +114,64 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
config_nav = self.find('#config-nav')
return config_nav.find_elements(By.TAG_NAME, 'li')[index]
+ def _get_create_builds(self, **kwargs):
+ """ Create a build and return the build object """
+ # parameters for builds to associate with the projects
+ now = timezone.now()
+ release = '3'
+ project_name = 'projectmaster'
+ self._create_test_new_project(
+ project_name+"2",
+ release,
+ False,
+ )
+
+ self.project1_build_success = {
+ 'project': Project.objects.get(id=1),
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.SUCCEEDED
+ }
+
+ self.project1_build_failure = {
+ 'project': Project.objects.get(id=1),
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.FAILED
+ }
+ build1 = Build.objects.create(**self.project1_build_success)
+ build2 = Build.objects.create(**self.project1_build_failure)
+
+ # add some targets to these builds so they have recipe links
+ # (and so we can find the row in the ToasterTable corresponding to
+ # a particular build)
+ Target.objects.create(build=build1, target='foo')
+ Target.objects.create(build=build2, target='bar')
+
+ if kwargs:
+ # Create kwargs.get('success') builds with success status with target
+ # and kwargs.get('failure') builds with failure status with target
+ for i in range(kwargs.get('success', 0)):
+ now = timezone.now()
+ self.project1_build_success['started_on'] = now
+ self.project1_build_success[
+ 'completed_on'] = now - timezone.timedelta(days=i)
+ build = Build.objects.create(**self.project1_build_success)
+ Target.objects.create(build=build,
+ target=f'{i}_success_recipe',
+ task=f'{i}_success_task')
+
+ for i in range(kwargs.get('failure', 0)):
+ now = timezone.now()
+ self.project1_build_failure['started_on'] = now
+ self.project1_build_failure[
+ 'completed_on'] = now - timezone.timedelta(days=i)
+ build = Build.objects.create(**self.project1_build_failure)
+ Target.objects.create(build=build,
+ target=f'{i}_fail_recipe',
+ task=f'{i}_fail_task')
+ return build1, build2
+
def test_project_config_nav(self):
""" Test project config tab navigation:
- Check if the menu is displayed and contains the right elements:
@@ -421,3 +481,64 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
'//div[@id="latest-builds"]/div'
)
self.assertTrue(len(lastest_builds) > 0)
+
+ def test_image_recipe_editColumn(self):
+ """ Test the edit column feature in image recipe table on project page """
+ self._get_create_builds(success=10, failure=10)
+
+ def test_edit_column(check_box_id):
+ # Check that we can hide/show table column
+ check_box = self.find(f'#{check_box_id}')
+ th_class = str(check_box_id).replace('checkbox-', '')
+ if check_box.is_selected():
+ # check if column is visible in table
+ self.assertTrue(
+ self.find(
+ f'#imagerecipestable thead th.{th_class}'
+ ).is_displayed(),
+ f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table"
+ )
+ check_box.click()
+ # check if column is hidden in table
+ self.assertFalse(
+ self.find(
+ f'#imagerecipestable thead th.{th_class}'
+ ).is_displayed(),
+ f"The {th_class} column is unchecked in EditColumn dropdown, but it's visible in table"
+ )
+ else:
+ # check if column is hidden in table
+ self.assertFalse(
+ self.find(
+ f'#imagerecipestable thead th.{th_class}'
+ ).is_displayed(),
+ f"The {th_class} column is unchecked in EditColumn dropdown, but it's visible in table"
+ )
+ check_box.click()
+ # check if column is visible in table
+ self.assertTrue(
+ self.find(
+ f'#imagerecipestable thead th.{th_class}'
+ ).is_displayed(),
+ f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table"
+ )
+
+ url = reverse('projectimagerecipes', args=(1,))
+ self.get(url)
+ self.wait_until_present('#imagerecipestable tbody tr')
+
+ # Check edit column
+ edit_column = self.find('#edit-columns-button')
+ self.assertTrue(edit_column.is_displayed())
+ edit_column.click()
+ # Check dropdown is visible
+ self.wait_until_visible('ul.dropdown-menu.editcol')
+
+ # Check that we can hide the edit column
+ test_edit_column('checkbox-get_description_or_summary')
+ test_edit_column('checkbox-layer_version__get_vcs_reference')
+ test_edit_column('checkbox-layer_version__layer__name')
+ test_edit_column('checkbox-license')
+ test_edit_column('checkbox-recipe-file')
+ test_edit_column('checkbox-section')
+ test_edit_column('checkbox-version')
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 7/7] Toaster: Write UI TestCase -> Test the show rows feature in image recipe
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
` (4 preceding siblings ...)
2023-11-21 13:50 ` [PATCH 6/7] Toaster: Write UI TestCase -> the edit column feature in image recipe Alassane Yattara
@ 2023-11-21 13:50 ` Alassane Yattara
5 siblings, 0 replies; 7+ messages in thread
From: Alassane Yattara @ 2023-11-21 13:50 UTC (permalink / raw)
To: toaster; +Cc: Alassane Yattara
Test the show rows feature in image recipe table on project page
Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com>
---
.../test_project_page_tab_config.py | 36 ++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/lib/toaster/tests/functional/test_project_page_tab_config.py b/lib/toaster/tests/functional/test_project_page_tab_config.py
index 2dfc120d..23012d78 100644
--- a/lib/toaster/tests/functional/test_project_page_tab_config.py
+++ b/lib/toaster/tests/functional/test_project_page_tab_config.py
@@ -347,7 +347,10 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
By.XPATH, '//*[@id="project-page"]/div[1]/div[3]')
recipe_list = most_built_recipes.find_element(By.ID, 'freq-build-list')
recipe_list_items = recipe_list.find_elements(By.TAG_NAME, 'li')
- self.assertTrue(len(recipe_list_items) > 0)
+ self.assertTrue(
+ len(recipe_list_items) > 0,
+ msg="No recipes found in the most built recipes list",
+ )
checkbox = recipe_list_items[0].find_element(By.TAG_NAME, 'input')
checkbox.click()
build_btn = self.find('#freq-build-btn')
@@ -465,6 +468,7 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
recipe_input = self.find('#search-input-imagerecipestable')
recipe_input.send_keys('core-image-minimal')
self.find('#search-submit-imagerecipestable').click()
+ self.wait_until_visible('#imagerecipestable tbody tr')
rows = self.find_all('#imagerecipestable tbody tr')
self.assertTrue(len(rows) > 0)
@@ -542,3 +546,33 @@ class TestProjectConfigTab(SeleniumFunctionalTestCase):
test_edit_column('checkbox-recipe-file')
test_edit_column('checkbox-section')
test_edit_column('checkbox-version')
+
+ def test_image_recipe_show_rows(self):
+ """ Test the show rows feature in image recipe table on project page """
+ self._get_create_builds(success=100, failure=100)
+
+ def test_show_rows(row_to_show, show_row_link):
+ # Check that we can show rows == row_to_show
+ show_row_link.select_by_value(str(row_to_show))
+ self.wait_until_present('#imagerecipestable tbody tr')
+ sleep(1)
+ self.assertTrue(
+ len(self.find_all('#imagerecipestable tbody tr')) == row_to_show
+ )
+
+ url = reverse('projectimagerecipes', args=(2,))
+ self.get(url)
+ self.wait_until_present('#imagerecipestable tbody tr')
+
+ show_rows = self.driver.find_elements(
+ By.XPATH,
+ '//select[@class="form-control pagesize-imagerecipestable"]'
+ )
+ # Check show rows
+ for show_row_link in show_rows:
+ show_row_link = Select(show_row_link)
+ test_show_rows(10, show_row_link)
+ test_show_rows(25, show_row_link)
+ test_show_rows(50, show_row_link)
+ test_show_rows(100, show_row_link)
+ test_show_rows(150, show_row_link)
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-11-21 13:51 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-21 13:50 [PATCH 1/7] Toaster: Write UI TestCase -> Test project config tab navigation: Alassane Yattara
2023-11-21 13:50 ` [PATCH 2/7] Toaster: Write UI TestCase -> Test project config tab Alassane Yattara
2023-11-21 13:50 ` [PATCH 3/7] Toaster: Write UI TestCase -> Test project page tab import layer Alassane Yattara
2023-11-21 13:50 ` [PATCH 4/7] Toaster: Write UI TestCase -> Test project page tab "New custom image" Alassane Yattara
2023-11-21 13:50 ` [PATCH 5/7] Toaster: Write UI TestCase -> Test project page section images Alassane Yattara
2023-11-21 13:50 ` [PATCH 6/7] Toaster: Write UI TestCase -> the edit column feature in image recipe Alassane Yattara
2023-11-21 13:50 ` [PATCH 7/7] Toaster: Write UI TestCase -> Test the show rows " Alassane Yattara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).