Skip to content

Commit

Permalink
UI: test downloading report through both kebab menu and modal
Browse files Browse the repository at this point in the history
  • Loading branch information
mirekdlugosz committed Dec 18, 2024
1 parent cd6ceb9 commit dc22f5f
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 8 deletions.
41 changes: 41 additions & 0 deletions camayoc/tests/qpc/ui/test_scans.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
from camayoc.tests.qpc.utils import assert_sha256sums
from camayoc.ui import Client
from camayoc.ui import data_factories
from camayoc.ui.enums import ColumnOrdering
from camayoc.ui.enums import MainMenuPages
from camayoc.ui.enums import ScansPopupTableColumns


def has_network_source(scan_name):
Expand All @@ -26,6 +28,7 @@ def has_network_source(scan_name):
continue
scan_sources = set(scan_definition.sources)
return bool(network_sources.intersection(scan_sources))
return False


def scan_names():
Expand Down Expand Up @@ -64,3 +67,41 @@ def test_download_scan(tmp_path, scans, ui_client: Client, scan_name):
tarfile.open(downloaded_report.path()).extractall(tmp_path)
assert_sha256sums(tmp_path)
assert_ansible_logs(tmp_path, is_network_scan)


@pytest.mark.nightly_only
@pytest.mark.parametrize("scan_name", scan_names())
def test_download_scan_modal(tmp_path, scans, ui_client: Client, scan_name):
"""Download finished scan using modal and verify basic content properties.
:id: 00fc7f4f-6f7a-4947-869e-749060a2285f
:description: This is almost exact copy of test_download_scan, except
this one clicks button in "Last scanned" column and uses modal
to download the scan results.
:steps:
1) Log into the UI.
2) Download finished scan report using the modal.
3) Verify downloaded file looks like a valid scan.
4) Log out.
:expectedresults: Report is downloaded. User is logged out.
"""
finished_scan = scans.with_name(scan_name)
(
ui_client.begin()
.login(data_factories.LoginFormDTOFactory())
.navigate_to(MainMenuPages.SCANS)
.download_scan_modal(
finished_scan.definition.name,
ScansPopupTableColumns.SCAN_TIME,
ColumnOrdering.DESCENDING,
0,
)
.logout()
)

is_network_scan = has_network_source(scan_name)
downloaded_report = ui_client.downloaded_files[-1]

tarfile.open(downloaded_report.path()).extractall(tmp_path)
assert_sha256sums(tmp_path)
assert_ansible_logs(tmp_path, is_network_scan)
10 changes: 10 additions & 0 deletions camayoc/ui/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,13 @@ class SourceConnectionTypes(StrEnum):
TLS11 = "TLSv1.1"
TLS12 = "TLSv1.2"
DISABLE = "Disable SSL"


class ScansPopupTableColumns(StrEnum):
SCAN_TIME = "header_scan_time"
SCAN_RESULT = "header_scan_result"


class ColumnOrdering(StrEnum):
ASCENDING = "ascending"
DESCENDING = "descending"
70 changes: 62 additions & 8 deletions camayoc/ui/models/pages/scans.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,43 @@
from camayoc.ui.decorators import creates_toast
from camayoc.ui.decorators import record_action
from camayoc.ui.decorators import service
from camayoc.ui.enums import ColumnOrdering
from camayoc.ui.enums import Pages
from camayoc.ui.enums import ScansPopupTableColumns

from ..components.items_list import AbstractListItem
from ..components.popup import PopUp
from ..mixins import MainPageMixin
from .abstract_page import AbstractPage

REFRESH_BUTTON_LOCATOR = "div[class*=-c-toolbar] button[data-ouia-component-id=refresh]"


class ScanHistoryPopup(PopUp, AbstractPage):
SAVE_LOCATOR = None
CANCEL_LOCATOR = "*[class$='modal-box__close'] button"
SAVE_RESULT_CLASS = None
CANCEL_RESULT_CLASS = Pages.SCANS

def get_last_download(self) -> Download:
def sort_table(self, sort_by: ScansPopupTableColumns, ordering: ColumnOrdering) -> None:
tries = 0
table_header_locator = (
"table[data-ouia-component-id=scan_jobs_table] thead "
f"th[data-ouia-component-id={sort_by.value}]"
)
while 3 >= tries:
header = self._driver.locator(table_header_locator)
if header.get_attribute("aria-sort") == ordering.value:
return
header.click()
tries += 1
raise RuntimeError("Failed to sort table")

def get_nth_download(self, item: int) -> Download:
table_row_locator = "table[data-ouia-component-id=scan_jobs_table] tbody tr"
download_button_locator = "td[data-label=Download] button"

last_download = self._driver.locator(table_row_locator).last
last_download = self._driver.locator(table_row_locator).nth(item)
with self._driver.expect_download() as download_info:
last_download.locator(download_button_locator).click(timeout=10_000)
download = download_info.value
Expand All @@ -37,22 +55,47 @@ def get_last_download(self) -> Download:

class ScanListElem(AbstractListItem):
def download_scan(self) -> Download:
timeout_start = time.monotonic()
timeout = self._client._camayoc_config.camayoc.scan_timeout
download_locator = (
"button[data-ouia-component-id=action_menu_toggle] "
"~ div *[data-ouia-component-id=download] button"
)
while timeout > (time.monotonic() - timeout_start):
try:
self._toggle_kebab()
with self._client.driver.expect_download() as download_info:
self.locator.locator(download_locator).click(timeout=10_000)
download = download_info.value
download.path() # blocks the script while file is downloaded
self._toggle_kebab()
return download
except PlaywrightTimeoutError:
self._client.driver.locator(REFRESH_BUTTON_LOCATOR).click()
raise FailedScanException("Scan could not be downloaded")

def download_scan_modal(
self, sort_by: ScansPopupTableColumns, ordering: ColumnOrdering, item: int
) -> Download:
timeout_start = time.monotonic()
timeout = self._client._camayoc_config.camayoc.scan_timeout
while timeout > (time.monotonic() - timeout_start):
try:
scans_popup = self._open_scans()
download = scans_popup.get_last_download()
scans_popup = self._open_scans_popup()
scans_popup.sort_table(sort_by, ordering)
download = scans_popup.get_nth_download(item)
scans_popup.cancel()
return download
except PlaywrightTimeoutError:
scans_popup.cancel()
self._client.driver.locator(
"div[class*=-c-toolbar] button[data-ouia-component-id=refresh]"
).click()
self._client.driver.locator(REFRESH_BUTTON_LOCATOR).click()
raise FailedScanException("Scan could not be downloaded")

def _open_scans(self) -> ScanHistoryPopup:
def _toggle_kebab(self) -> None:
kebab_menu_locator = "button[data-ouia-component-id=action_menu_toggle]"
self.locator.locator(kebab_menu_locator).click()

def _open_scans_popup(self) -> ScanHistoryPopup:
last_scanned_locator = "td[data-label='Last scanned'] button"
self.locator.locator(last_scanned_locator).click()
return ScanHistoryPopup(client=self._client)
Expand All @@ -69,3 +112,14 @@ def download_scan(self, scan_name: str) -> ScansMainPage:
downloaded_report = scan.download_scan()
self._client.downloaded_files.append(downloaded_report)
return self

@creates_toast
@service
@record_action
def download_scan_modal(
self, scan_name: str, sort_by: ScansPopupTableColumns, ordering: ColumnOrdering, item: int
) -> ScansMainPage:
scan: ScanListElem = self._get_item(scan_name)
downloaded_report = scan.download_scan_modal(sort_by, ordering, item)
self._client.downloaded_files.append(downloaded_report)
return self

0 comments on commit dc22f5f

Please sign in to comment.