mirror of
https://git.yoctoproject.org/poky
synced 2026-02-11 19:23:03 +01:00
Test if some rows are visible in table instead of compare row to row_to_show, because sometime full avaiblable content did not display Failed: https://autobuilder.yoctoproject.org/typhoon/#/builders/161/builds/147/steps/12/logs/stdio (Bitbake rev: 5b0a48265aafa62259c575707c3afa6dd56f8008) Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
793 lines
32 KiB
Python
793 lines
32 KiB
Python
#! /usr/bin/env python3 #
|
|
# BitBake Toaster UI tests implementation
|
|
#
|
|
# Copyright (C) 2023 Savoir-faire Linux
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
#
|
|
|
|
import os
|
|
import random
|
|
import string
|
|
from unittest import skip
|
|
import pytest
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from selenium.webdriver.common.keys import Keys
|
|
from selenium.webdriver.support.select import Select
|
|
from selenium.common.exceptions import TimeoutException
|
|
from tests.functional.functional_helpers import SeleniumFunctionalTestCase
|
|
from orm.models import Build, Project, Target
|
|
from selenium.webdriver.common.by import By
|
|
|
|
from .utils import get_projectId_from_url, wait_until_build, wait_until_build_cancelled
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@pytest.mark.order("last")
|
|
class TestProjectPage(SeleniumFunctionalTestCase):
|
|
project_id = None
|
|
PROJECT_NAME = 'TestProjectPage'
|
|
|
|
def _create_project(self, project_name):
|
|
""" Create/Test new project using:
|
|
- Project Name: Any string
|
|
- Release: Any string
|
|
- Merge Toaster settings: True or False
|
|
"""
|
|
self.get(reverse('newproject'))
|
|
self.wait_until_visible('#new-project-name')
|
|
self.find("#new-project-name").send_keys(project_name)
|
|
select = Select(self.find("#projectversion"))
|
|
select.select_by_value('3')
|
|
|
|
# check merge toaster settings
|
|
checkbox = self.find('.checkbox-mergeattr')
|
|
if not checkbox.is_selected():
|
|
checkbox.click()
|
|
|
|
if self.PROJECT_NAME != 'TestProjectPage':
|
|
# Reset project name if it's not the default one
|
|
self.PROJECT_NAME = 'TestProjectPage'
|
|
|
|
self.find("#create-project-button").click()
|
|
|
|
try:
|
|
self.wait_until_visible('#hint-error-project-name')
|
|
url = reverse('project', args=(TestProjectPage.project_id, ))
|
|
self.get(url)
|
|
self.wait_until_visible('#config-nav', poll=3)
|
|
except TimeoutException:
|
|
self.wait_until_visible('#config-nav', poll=3)
|
|
|
|
def _random_string(self, length):
|
|
return ''.join(
|
|
random.choice(string.ascii_letters) for _ in range(length)
|
|
)
|
|
|
|
def _navigate_to_project_page(self):
|
|
# Navigate to project page
|
|
if TestProjectPage.project_id is None:
|
|
self._create_project(project_name=self._random_string(10))
|
|
current_url = self.driver.current_url
|
|
TestProjectPage.project_id = get_projectId_from_url(current_url)
|
|
else:
|
|
url = reverse('project', args=(TestProjectPage.project_id,))
|
|
self.get(url)
|
|
self.wait_until_visible('#config-nav')
|
|
|
|
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()
|
|
self.project1_build_success = {
|
|
'project': Project.objects.get(id=TestProjectPage.project_id),
|
|
'started_on': now,
|
|
'completed_on': now,
|
|
'outcome': Build.SUCCEEDED
|
|
}
|
|
|
|
self.project1_build_failure = {
|
|
'project': Project.objects.get(id=TestProjectPage.project_id),
|
|
'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 _mixin_test_table_edit_column(
|
|
self,
|
|
table_id,
|
|
edit_btn_id,
|
|
list_check_box_id: list
|
|
):
|
|
# Check edit column
|
|
edit_column = self.find(f'#{edit_btn_id}')
|
|
self.assertTrue(edit_column.is_displayed())
|
|
edit_column.click()
|
|
# Check dropdown is visible
|
|
self.wait_until_visible('ul.dropdown-menu.editcol')
|
|
for check_box_id in list_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'#{table_id} 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'#{table_id} 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'#{table_id} 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'#{table_id} thead th.{th_class}'
|
|
).is_displayed(),
|
|
f"The {th_class} column is checked in EditColumn dropdown, but it's not visible in table"
|
|
)
|
|
|
|
def _get_config_nav_item(self, index):
|
|
config_nav = self.find('#config-nav')
|
|
return config_nav.find_elements(By.TAG_NAME, 'li')[index]
|
|
|
|
def _navigate_to_config_nav(self, nav_id, nav_index):
|
|
# navigate to the project page
|
|
self._navigate_to_project_page()
|
|
# click on "Software recipe" tab
|
|
soft_recipe = self._get_config_nav_item(nav_index)
|
|
soft_recipe.click()
|
|
self.wait_until_visible(f'#{nav_id}')
|
|
|
|
def _mixin_test_table_show_rows(self, table_selector, **kwargs):
|
|
""" Test the show rows feature in the builds table on the all builds page """
|
|
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_visible(f'#{table_selector} tbody tr', poll=3)
|
|
# check at least some rows are visible
|
|
self.assertTrue(
|
|
len(self.find_all(f'#{table_selector} tbody tr')) > 0
|
|
)
|
|
self.wait_until_present(f'#{table_selector} tbody tr')
|
|
show_rows = self.driver.find_elements(
|
|
By.XPATH,
|
|
f'//select[@class="form-control pagesize-{table_selector}"]'
|
|
)
|
|
rows_to_show = [10, 25, 50, 100, 150]
|
|
to_skip = kwargs.get('to_skip', [])
|
|
# Check show rows
|
|
for show_row_link in show_rows:
|
|
show_row_link = Select(show_row_link)
|
|
for row_to_show in rows_to_show:
|
|
if row_to_show not in to_skip:
|
|
test_show_rows(row_to_show, show_row_link)
|
|
|
|
def _mixin_test_table_search_input(self, **kwargs):
|
|
input_selector, input_text, searchBtn_selector, table_selector, *_ = kwargs.values()
|
|
# Test search input
|
|
self.wait_until_visible(f'#{input_selector}')
|
|
recipe_input = self.find(f'#{input_selector}')
|
|
recipe_input.send_keys(input_text)
|
|
self.find(f'#{searchBtn_selector}').click()
|
|
self.wait_until_visible(f'#{table_selector} tbody tr')
|
|
rows = self.find_all(f'#{table_selector} tbody tr')
|
|
self.assertTrue(len(rows) > 0)
|
|
|
|
def test_create_project(self):
|
|
""" Create/Test new project using:
|
|
- Project Name: Any string
|
|
- Release: Any string
|
|
- Merge Toaster settings: True or False
|
|
"""
|
|
self._create_project(project_name=self.PROJECT_NAME)
|
|
|
|
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)
|
|
|
|
url = reverse('projectimagerecipes', args=(TestProjectPage.project_id,))
|
|
self.get(url)
|
|
self.wait_until_present('#imagerecipestable tbody tr')
|
|
|
|
column_list = [
|
|
'get_description_or_summary', 'layer_version__get_vcs_reference',
|
|
'layer_version__layer__name', 'license', 'recipe-file', 'section',
|
|
'version'
|
|
]
|
|
|
|
# Check that we can hide the edit column
|
|
self._mixin_test_table_edit_column(
|
|
'imagerecipestable',
|
|
'edit-columns-button',
|
|
[f'checkbox-{column}' for column in column_list]
|
|
)
|
|
|
|
def test_page_header_on_project_page(self):
|
|
""" Check page header in project page:
|
|
- AT LEFT -> Logo of Yocto project, displayed, clickable
|
|
- "Toaster"+" Information icon", displayed, clickable
|
|
- "Server Icon" + "All builds", displayed, clickable
|
|
- "Directory Icon" + "All projects", displayed, clickable
|
|
- "Book Icon" + "Documentation", displayed, clickable
|
|
- AT RIGHT -> button "New project", displayed, clickable
|
|
"""
|
|
# navigate to the project page
|
|
self._navigate_to_project_page()
|
|
|
|
# check page header
|
|
# AT LEFT -> Logo of Yocto project
|
|
logo = self.driver.find_element(
|
|
By.XPATH,
|
|
"//div[@class='toaster-navbar-brand']",
|
|
)
|
|
logo_img = logo.find_element(By.TAG_NAME, 'img')
|
|
self.assertTrue(logo_img.is_displayed(),
|
|
'Logo of Yocto project not found')
|
|
self.assertTrue(
|
|
'/static/img/logo.png' in str(logo_img.get_attribute('src')),
|
|
'Logo of Yocto project not found'
|
|
)
|
|
# "Toaster"+" Information icon", clickable
|
|
toaster = self.driver.find_element(
|
|
By.XPATH,
|
|
"//div[@class='toaster-navbar-brand']//a[@class='brand']",
|
|
)
|
|
self.assertTrue(toaster.is_displayed(), 'Toaster not found')
|
|
self.assertTrue(toaster.text == 'Toaster')
|
|
info_sign = self.find('.glyphicon-info-sign')
|
|
self.assertTrue(info_sign.is_displayed())
|
|
|
|
# "Server Icon" + "All builds"
|
|
all_builds = self.find('#navbar-all-builds')
|
|
all_builds_link = all_builds.find_element(By.TAG_NAME, 'a')
|
|
self.assertTrue("All builds" in all_builds_link.text)
|
|
self.assertTrue(
|
|
'/toastergui/builds/' in str(all_builds_link.get_attribute('href'))
|
|
)
|
|
server_icon = all_builds.find_element(By.TAG_NAME, 'i')
|
|
self.assertTrue(
|
|
server_icon.get_attribute('class') == 'glyphicon glyphicon-tasks'
|
|
)
|
|
self.assertTrue(server_icon.is_displayed())
|
|
|
|
# "Directory Icon" + "All projects"
|
|
all_projects = self.find('#navbar-all-projects')
|
|
all_projects_link = all_projects.find_element(By.TAG_NAME, 'a')
|
|
self.assertTrue("All projects" in all_projects_link.text)
|
|
self.assertTrue(
|
|
'/toastergui/projects/' in str(all_projects_link.get_attribute(
|
|
'href'))
|
|
)
|
|
dir_icon = all_projects.find_element(By.TAG_NAME, 'i')
|
|
self.assertTrue(
|
|
dir_icon.get_attribute('class') == 'icon-folder-open'
|
|
)
|
|
self.assertTrue(dir_icon.is_displayed())
|
|
|
|
# "Book Icon" + "Documentation"
|
|
toaster_docs_link = self.find('#navbar-docs')
|
|
toaster_docs_link_link = toaster_docs_link.find_element(By.TAG_NAME,
|
|
'a')
|
|
self.assertTrue("Documentation" in toaster_docs_link_link.text)
|
|
self.assertTrue(
|
|
toaster_docs_link_link.get_attribute('href') == 'http://docs.yoctoproject.org/toaster-manual/index.html#toaster-user-manual'
|
|
)
|
|
book_icon = toaster_docs_link.find_element(By.TAG_NAME, 'i')
|
|
self.assertTrue(
|
|
book_icon.get_attribute('class') == 'glyphicon glyphicon-book'
|
|
)
|
|
self.assertTrue(book_icon.is_displayed())
|
|
|
|
# AT RIGHT -> button "New project"
|
|
new_project_button = self.find('#new-project-button')
|
|
self.assertTrue(new_project_button.is_displayed())
|
|
self.assertTrue(new_project_button.text == 'New project')
|
|
new_project_button.click()
|
|
self.assertTrue(
|
|
'/toastergui/newproject/' in str(self.driver.current_url)
|
|
)
|
|
|
|
def test_edit_project_name(self):
|
|
""" Test edit project name:
|
|
- Click on "Edit" icon button
|
|
- Change project name
|
|
- Click on "Save" button
|
|
- Check project name is changed
|
|
"""
|
|
# navigate to the project page
|
|
self._navigate_to_project_page()
|
|
|
|
# click on "Edit" icon button
|
|
self.wait_until_visible('#project-name-container')
|
|
edit_button = self.find('#project-change-form-toggle')
|
|
edit_button.click()
|
|
project_name_input = self.find('#project-name-change-input')
|
|
self.assertTrue(project_name_input.is_displayed())
|
|
project_name_input.clear()
|
|
project_name_input.send_keys('New Name')
|
|
self.find('#project-name-change-btn').click()
|
|
|
|
# check project name is changed
|
|
self.wait_until_visible('#project-name-container')
|
|
self.assertTrue(
|
|
'New Name' in str(self.find('#project-name-container').text)
|
|
)
|
|
|
|
def test_project_page_tabs(self):
|
|
""" Test project tabs:
|
|
- "configuration" tab
|
|
- "Builds" tab
|
|
- "Import layers" tab
|
|
- "New custom image" tab
|
|
Check search box used to build recipes
|
|
"""
|
|
# navigate to the project page
|
|
self._navigate_to_project_page()
|
|
|
|
# check "configuration" tab
|
|
self.wait_until_visible('#topbar-configuration-tab')
|
|
config_tab = self.find('#topbar-configuration-tab')
|
|
self.assertTrue(config_tab.get_attribute('class') == 'active')
|
|
self.assertTrue('Configuration' in str(config_tab.text))
|
|
self.assertTrue(
|
|
f"/toastergui/project/{TestProjectPage.project_id}" in str(self.driver.current_url)
|
|
)
|
|
|
|
def get_tabs():
|
|
# tabs links list
|
|
return self.driver.find_elements(
|
|
By.XPATH,
|
|
'//div[@id="project-topbar"]//li'
|
|
)
|
|
|
|
def check_tab_link(tab_index, tab_name, url):
|
|
tab = get_tabs()[tab_index]
|
|
tab_link = tab.find_element(By.TAG_NAME, 'a')
|
|
self.assertTrue(url in tab_link.get_attribute('href'))
|
|
self.assertTrue(tab_name in tab_link.text)
|
|
self.assertTrue(tab.get_attribute('class') == 'active')
|
|
|
|
# check "Builds" tab
|
|
builds_tab = get_tabs()[1]
|
|
builds_tab.find_element(By.TAG_NAME, 'a').click()
|
|
check_tab_link(
|
|
1,
|
|
'Builds',
|
|
f"/toastergui/project/{TestProjectPage.project_id}/builds"
|
|
)
|
|
|
|
# check "Import layers" tab
|
|
import_layers_tab = get_tabs()[2]
|
|
import_layers_tab.find_element(By.TAG_NAME, 'a').click()
|
|
check_tab_link(
|
|
2,
|
|
'Import layer',
|
|
f"/toastergui/project/{TestProjectPage.project_id}/importlayer"
|
|
)
|
|
|
|
# check "New custom image" tab
|
|
new_custom_image_tab = get_tabs()[3]
|
|
new_custom_image_tab.find_element(By.TAG_NAME, 'a').click()
|
|
check_tab_link(
|
|
3,
|
|
'New custom image',
|
|
f"/toastergui/project/{TestProjectPage.project_id}/newcustomimage"
|
|
)
|
|
|
|
# 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()
|
|
self.wait_until_visible('#latest-builds')
|
|
lastest_builds = self.driver.find_elements(
|
|
By.XPATH,
|
|
'//div[@id="latest-builds"]',
|
|
)
|
|
last_build = lastest_builds[0]
|
|
self.assertTrue(
|
|
'core-image-minimal' in str(last_build.text)
|
|
)
|
|
|
|
def test_softwareRecipe_page(self):
|
|
""" Test software recipe page
|
|
- Check title "Compatible software recipes" is displayed
|
|
- Check search input
|
|
- Check "build recipe" button works
|
|
- Check software recipe table feature(show/hide column, pagination)
|
|
"""
|
|
self._navigate_to_config_nav('softwarerecipestable', 4)
|
|
# check title "Compatible software recipes" is displayed
|
|
self.assertTrue("Compatible software recipes" in self.get_page_source())
|
|
# Test search input
|
|
self._mixin_test_table_search_input(
|
|
input_selector='search-input-softwarerecipestable',
|
|
input_text='busybox',
|
|
searchBtn_selector='search-submit-softwarerecipestable',
|
|
table_selector='softwarerecipestable'
|
|
)
|
|
# check "build recipe" button works
|
|
rows = self.find_all('#softwarerecipestable tbody tr')
|
|
image_to_build = rows[0]
|
|
build_btn = image_to_build.find_element(
|
|
By.XPATH,
|
|
'//td[@class="add-del-layers"]//a[1]'
|
|
)
|
|
build_btn.click()
|
|
build_state = wait_until_build(self, 'queued cloning starting parsing failed')
|
|
lastest_builds = self.driver.find_elements(
|
|
By.XPATH,
|
|
'//div[@id="latest-builds"]/div'
|
|
)
|
|
self.assertTrue(len(lastest_builds) > 0)
|
|
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()
|
|
if 'starting' not in build_state: # change build state when cancelled in starting state
|
|
wait_until_build_cancelled(self)
|
|
|
|
# check software recipe table feature(show/hide column, pagination)
|
|
self._navigate_to_config_nav('softwarerecipestable', 4)
|
|
column_list = [
|
|
'get_description_or_summary',
|
|
'layer_version__get_vcs_reference',
|
|
'layer_version__layer__name',
|
|
'license',
|
|
'recipe-file',
|
|
'section',
|
|
'version',
|
|
]
|
|
self._mixin_test_table_edit_column(
|
|
'softwarerecipestable',
|
|
'edit-columns-button',
|
|
[f'checkbox-{column}' for column in column_list]
|
|
)
|
|
self._navigate_to_config_nav('softwarerecipestable', 4)
|
|
# check show rows(pagination)
|
|
self._mixin_test_table_show_rows(
|
|
table_selector='softwarerecipestable',
|
|
to_skip=[150],
|
|
)
|
|
|
|
def test_machines_page(self):
|
|
""" Test Machine page
|
|
- Check if title "Compatible machines" is displayed
|
|
- Check search input
|
|
- Check "Select machine" button works
|
|
- Check "Add layer" button works
|
|
- Check Machine table feature(show/hide column, pagination)
|
|
"""
|
|
self._navigate_to_config_nav('machinestable', 5)
|
|
# check title "Compatible software recipes" is displayed
|
|
self.assertTrue("Compatible machines" in self.get_page_source())
|
|
# Test search input
|
|
self._mixin_test_table_search_input(
|
|
input_selector='search-input-machinestable',
|
|
input_text='qemux86-64',
|
|
searchBtn_selector='search-submit-machinestable',
|
|
table_selector='machinestable'
|
|
)
|
|
# check "Select machine" button works
|
|
rows = self.find_all('#machinestable tbody tr')
|
|
machine_to_select = rows[0]
|
|
select_btn = machine_to_select.find_element(
|
|
By.XPATH,
|
|
'//td[@class="add-del-layers"]//a[1]'
|
|
)
|
|
select_btn.send_keys(Keys.RETURN)
|
|
self.wait_until_visible('#config-nav')
|
|
project_machine_name = self.find('#project-machine-name')
|
|
self.assertTrue(
|
|
'qemux86-64' in project_machine_name.text
|
|
)
|
|
# check "Add layer" button works
|
|
self._navigate_to_config_nav('machinestable', 5)
|
|
# Search for a machine whit layer not in project
|
|
self._mixin_test_table_search_input(
|
|
input_selector='search-input-machinestable',
|
|
input_text='qemux86-64-tpm2',
|
|
searchBtn_selector='search-submit-machinestable',
|
|
table_selector='machinestable'
|
|
)
|
|
self.wait_until_visible('#machinestable tbody tr', poll=3)
|
|
rows = self.find_all('#machinestable tbody tr')
|
|
machine_to_add = rows[0]
|
|
add_btn = machine_to_add.find_element(By.XPATH, '//td[@class="add-del-layers"]')
|
|
add_btn.click()
|
|
self.wait_until_visible('#change-notification')
|
|
change_notification = self.find('#change-notification')
|
|
self.assertTrue(
|
|
f'You have added 1 layer to your project' in str(change_notification.text)
|
|
)
|
|
# check Machine table feature(show/hide column, pagination)
|
|
self._navigate_to_config_nav('machinestable', 5)
|
|
column_list = [
|
|
'description',
|
|
'layer_version__get_vcs_reference',
|
|
'layer_version__layer__name',
|
|
'machinefile',
|
|
]
|
|
self._mixin_test_table_edit_column(
|
|
'machinestable',
|
|
'edit-columns-button',
|
|
[f'checkbox-{column}' for column in column_list]
|
|
)
|
|
self._navigate_to_config_nav('machinestable', 5)
|
|
# check show rows(pagination)
|
|
self._mixin_test_table_show_rows(
|
|
table_selector='machinestable',
|
|
to_skip=[150],
|
|
)
|
|
|
|
def test_layers_page(self):
|
|
""" Test layers page
|
|
- Check if title "Compatible layerss" is displayed
|
|
- Check search input
|
|
- Check "Add layer" button works
|
|
- Check "Remove layer" button works
|
|
- Check layers table feature(show/hide column, pagination)
|
|
"""
|
|
self._navigate_to_config_nav('layerstable', 6)
|
|
# check title "Compatible layers" is displayed
|
|
self.assertTrue("Compatible layers" in self.get_page_source())
|
|
# Test search input
|
|
input_text='meta-tanowrt'
|
|
self._mixin_test_table_search_input(
|
|
input_selector='search-input-layerstable',
|
|
input_text=input_text,
|
|
searchBtn_selector='search-submit-layerstable',
|
|
table_selector='layerstable'
|
|
)
|
|
# check "Add layer" button works
|
|
self.wait_until_visible('#layerstable tbody tr', poll=3)
|
|
rows = self.find_all('#layerstable tbody tr')
|
|
layer_to_add = rows[0]
|
|
add_btn = layer_to_add.find_element(
|
|
By.XPATH,
|
|
'//td[@class="add-del-layers"]'
|
|
)
|
|
add_btn.click()
|
|
# check modal is displayed
|
|
self.wait_until_visible('#dependencies-modal', poll=3)
|
|
list_dependencies = self.find_all('#dependencies-list li')
|
|
# click on add-layers button
|
|
add_layers_btn = self.driver.find_element(
|
|
By.XPATH,
|
|
'//form[@id="dependencies-modal-form"]//button[@class="btn btn-primary"]'
|
|
)
|
|
add_layers_btn.click()
|
|
self.wait_until_visible('#change-notification')
|
|
change_notification = self.find('#change-notification')
|
|
self.assertTrue(
|
|
f'You have added {len(list_dependencies)+1} layers to your project: {input_text} and its dependencies' in str(change_notification.text)
|
|
)
|
|
# check "Remove layer" button works
|
|
self.wait_until_visible('#layerstable tbody tr', poll=3)
|
|
rows = self.find_all('#layerstable tbody tr')
|
|
layer_to_remove = rows[0]
|
|
remove_btn = layer_to_remove.find_element(
|
|
By.XPATH,
|
|
'//td[@class="add-del-layers"]'
|
|
)
|
|
remove_btn.click()
|
|
self.wait_until_visible('#change-notification', poll=2)
|
|
change_notification = self.find('#change-notification')
|
|
self.assertTrue(
|
|
f'You have removed 1 layer from your project: {input_text}' in str(change_notification.text)
|
|
)
|
|
# check layers table feature(show/hide column, pagination)
|
|
self._navigate_to_config_nav('layerstable', 6)
|
|
column_list = [
|
|
'dependencies',
|
|
'revision',
|
|
'layer__vcs_url',
|
|
'git_subdir',
|
|
'layer__summary',
|
|
]
|
|
self._mixin_test_table_edit_column(
|
|
'layerstable',
|
|
'edit-columns-button',
|
|
[f'checkbox-{column}' for column in column_list]
|
|
)
|
|
self._navigate_to_config_nav('layerstable', 6)
|
|
# check show rows(pagination)
|
|
self._mixin_test_table_show_rows(
|
|
table_selector='layerstable',
|
|
to_skip=[150],
|
|
)
|
|
|
|
def test_distro_page(self):
|
|
""" Test distros page
|
|
- Check if title "Compatible distros" is displayed
|
|
- Check search input
|
|
- Check "Add layer" button works
|
|
- Check distro table feature(show/hide column, pagination)
|
|
"""
|
|
self._navigate_to_config_nav('distrostable', 7)
|
|
# check title "Compatible distros" is displayed
|
|
self.assertTrue("Compatible Distros" in self.get_page_source())
|
|
# Test search input
|
|
input_text='poky-altcfg'
|
|
self._mixin_test_table_search_input(
|
|
input_selector='search-input-distrostable',
|
|
input_text=input_text,
|
|
searchBtn_selector='search-submit-distrostable',
|
|
table_selector='distrostable'
|
|
)
|
|
# check "Add distro" button works
|
|
rows = self.find_all('#distrostable tbody tr')
|
|
distro_to_add = rows[0]
|
|
add_btn = distro_to_add.find_element(
|
|
By.XPATH,
|
|
'//td[@class="add-del-layers"]//a[1]'
|
|
)
|
|
add_btn.click()
|
|
self.wait_until_visible('#change-notification', poll=2)
|
|
change_notification = self.find('#change-notification')
|
|
self.assertTrue(
|
|
f'You have changed the distro to: {input_text}' in str(change_notification.text)
|
|
)
|
|
# check distro table feature(show/hide column, pagination)
|
|
self._navigate_to_config_nav('distrostable', 7)
|
|
column_list = [
|
|
'description',
|
|
'templatefile',
|
|
'layer_version__get_vcs_reference',
|
|
'layer_version__layer__name',
|
|
]
|
|
self._mixin_test_table_edit_column(
|
|
'distrostable',
|
|
'edit-columns-button',
|
|
[f'checkbox-{column}' for column in column_list]
|
|
)
|
|
self._navigate_to_config_nav('distrostable', 7)
|
|
# check show rows(pagination)
|
|
self._mixin_test_table_show_rows(
|
|
table_selector='distrostable',
|
|
to_skip=[150],
|
|
)
|
|
|
|
def test_single_layer_page(self):
|
|
""" Test layer page
|
|
- Check if title is displayed
|
|
- Check add/remove layer button works
|
|
- Check tabs(layers, recipes, machines) are displayed
|
|
- Check left section is displayed
|
|
- Check layer name
|
|
- Check layer summary
|
|
- Check layer description
|
|
"""
|
|
url = reverse("layerdetails", args=(TestProjectPage.project_id, 8))
|
|
self.get(url)
|
|
self.wait_until_visible('.page-header')
|
|
# check title is displayed
|
|
self.assertTrue(self.find('.page-header h1').is_displayed())
|
|
|
|
# check add layer button works
|
|
remove_layer_btn = self.find('#add-remove-layer-btn')
|
|
remove_layer_btn.click()
|
|
self.wait_until_visible('#change-notification', poll=2)
|
|
change_notification = self.find('#change-notification')
|
|
self.assertTrue(
|
|
f'You have removed 1 layer from your project' in str(change_notification.text)
|
|
)
|
|
# check add layer button works, 18 is the random layer id
|
|
add_layer_btn = self.find('#add-remove-layer-btn')
|
|
add_layer_btn.click()
|
|
self.wait_until_visible('#change-notification')
|
|
change_notification = self.find('#change-notification')
|
|
self.assertTrue(
|
|
f'You have added 1 layer to your project' in str(change_notification.text)
|
|
)
|
|
# check tabs(layers, recipes, machines) are displayed
|
|
tabs = self.find_all('.nav-tabs li')
|
|
self.assertEqual(len(tabs), 3)
|
|
# Check first tab
|
|
tabs[0].click()
|
|
self.assertTrue(
|
|
'active' in str(self.find('#information').get_attribute('class'))
|
|
)
|
|
# Check second tab
|
|
tabs[1].click()
|
|
self.assertTrue(
|
|
'active' in str(self.find('#recipes').get_attribute('class'))
|
|
)
|
|
# Check third tab
|
|
tabs[2].click()
|
|
self.assertTrue(
|
|
'active' in str(self.find('#machines').get_attribute('class'))
|
|
)
|
|
# Check left section is displayed
|
|
section = self.find('.well')
|
|
# Check layer name
|
|
self.assertTrue(
|
|
section.find_element(By.XPATH, '//h2[1]').is_displayed()
|
|
)
|
|
# Check layer summary
|
|
self.assertTrue("Summary" in section.text)
|
|
# Check layer description
|
|
self.assertTrue("Description" in section.text)
|
|
|
|
def test_single_recipe_page(self):
|
|
""" Test recipe page
|
|
- Check if title is displayed
|
|
- Check add recipe layer displayed
|
|
- Check left section is displayed
|
|
- Check recipe: name, summary, description, Version, Section,
|
|
License, Approx. packages included, Approx. size, Recipe file
|
|
"""
|
|
url = reverse("recipedetails", args=(TestProjectPage.project_id, 53428))
|
|
self.get(url)
|
|
self.wait_until_visible('.page-header')
|
|
# check title is displayed
|
|
self.assertTrue(self.find('.page-header h1').is_displayed())
|
|
# check add recipe layer displayed
|
|
add_recipe_layer_btn = self.find('#add-layer-btn')
|
|
self.assertTrue(add_recipe_layer_btn.is_displayed())
|
|
# check left section is displayed
|
|
section = self.find('.well')
|
|
# Check recipe name
|
|
self.assertTrue(
|
|
section.find_element(By.XPATH, '//h2[1]').is_displayed()
|
|
)
|
|
# Check recipe sections details info are displayed
|
|
self.assertTrue("Summary" in section.text)
|
|
self.assertTrue("Description" in section.text)
|
|
self.assertTrue("Version" in section.text)
|
|
self.assertTrue("Section" in section.text)
|
|
self.assertTrue("License" in section.text)
|
|
self.assertTrue("Approx. packages included" in section.text)
|
|
self.assertTrue("Approx. package size" in section.text)
|
|
self.assertTrue("Recipe file" in section.text)
|