Skip to content

Commit

Permalink
Introduce shared component for interacting with "Add ..." dropdown
Browse files Browse the repository at this point in the history
When testing locally, occasionally we encounter the issue that clicking
"Add ..." button does not open dropdown (or dropdown disappears before
we can interact with it - impossible to tell). We need to wrap "click
add button and select item from dropdown" sequence in a loop, to retry
it. Since this is a component used in two places, we extract it to
shared component instead of repeating the loop.
  • Loading branch information
mirekdlugosz committed Oct 3, 2024
1 parent 8f6a99f commit 915059c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 48 deletions.
34 changes: 34 additions & 0 deletions camayoc/ui/models/components/add_new_dropdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from __future__ import annotations

from playwright.sync_api import TimeoutError

from camayoc.exceptions import MisconfiguredWidgetException
from camayoc.types.ui import UIPage


class AddNewDropdown(UIPage):
def open_create_new_modal(self, type_ouiaid):
default_timeout = 5000 # 5s
add_button_locator = getattr(self, "ADD_BUTTON_LOCATOR")
if not add_button_locator:
msg = "{} requires class property 'ADD_BUTTON_LOCATOR' to be set [object={}]"
raise MisconfiguredWidgetException(msg.format(type(self).__name__, self))

dropdown_item_locator = (
f"{add_button_locator} ~ div ul li[data-ouia-component-id={type_ouiaid}]"
)

exp_msg = (
"Could not open modal using dropdown menu [button locator={} ;"
"dropdown item locator={}]"
).format(add_button_locator, dropdown_item_locator)
exp = TimeoutError(exp_msg)
for _ in range(5):
try:
self._driver.locator(add_button_locator).click(timeout=default_timeout)
self._driver.locator(dropdown_item_locator).click(timeout=default_timeout)
return
except TimeoutError as e:
exp = e
continue
raise exp
74 changes: 39 additions & 35 deletions camayoc/ui/models/pages/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from camayoc.ui.enums import CredentialTypes
from camayoc.ui.enums import Pages

from ..components.add_new_dropdown import AddNewDropdown
from ..components.form import Form
from ..components.popup import PopUp
from ..fields import InputField
Expand Down Expand Up @@ -136,7 +137,9 @@ def fill(self, data: RHACSCredentialFormDTO):
return self


class CredentialsMainPage(MainPageMixin):
class CredentialsMainPage(AddNewDropdown, MainPageMixin):
ADD_BUTTON_LOCATOR = "button[data-ouia-component-id=add_credential_button]"

@service
def add_credential(self, data: AddCredentialDTO) -> CredentialsMainPage:
add_credential_popup = self.open_add_credential(data.credential_type)
Expand All @@ -145,6 +148,9 @@ def add_credential(self, data: AddCredentialDTO) -> CredentialsMainPage:

@record_action
def open_add_credential(self, source_type: CredentialTypes) -> CredentialForm:
if self._use_uiv2:
return self._open_add_credential_v2(source_type)

create_credential_button = "div[data-ouia-component-id=add_credential] > button"
source_type_map = {
CredentialTypes.NETWORK: {
Expand Down Expand Up @@ -173,43 +179,41 @@ def open_add_credential(self, source_type: CredentialTypes) -> CredentialForm:
},
}

# these selectors get few characters over allowed line length limit,
# in part due to indentation caused by conditional. Temporarily
# disable ruff rule for a file - we'll introduce correct solution when
# we remove old UI support
# ruff: noqa: E501
if self._use_uiv2:
create_credential_button = "button[data-ouia-component-id=add_credential_button]"
source_type_map = {
CredentialTypes.NETWORK: {
"selector": f"{create_credential_button} ~ div ul li[data-ouia-component-id=network]",
"class": NetworkCredentialForm,
},
CredentialTypes.SATELLITE: {
"selector": f"{create_credential_button} ~ div ul li[data-ouia-component-id=satellite]",
"class": SatelliteCredentialForm,
},
CredentialTypes.VCENTER: {
"selector": f"{create_credential_button} ~ div ul li[data-ouia-component-id=vcenter]",
"class": VCenterCredentialForm,
},
CredentialTypes.OPENSHIFT: {
"selector": f"{create_credential_button} ~ div ul li[data-ouia-component-id=openshift]",
"class": OpenShiftCredentialForm,
},
CredentialTypes.ANSIBLE: {
"selector": f"{create_credential_button} ~ div ul li[data-ouia-component-id=ansible]",
"class": AnsibleCredentialForm,
},
CredentialTypes.RHACS: {
"selector": f"{create_credential_button} ~ div ul li[data-ouia-component-id=rhacs]",
"class": RHACSCredentialForm,
},
}

selector, cls = source_type_map.get(source_type).values()

self._driver.click(create_credential_button)
self._driver.click(selector)

return self._new_page(cls)

def _open_add_credential_v2(self, source_type: CredentialTypes) -> CredentialForm:
source_type_map = {
CredentialTypes.NETWORK: {
"ouiaid": "network",
"class": NetworkCredentialForm,
},
CredentialTypes.SATELLITE: {
"ouiaid": "satellite",
"class": SatelliteCredentialForm,
},
CredentialTypes.VCENTER: {
"ouiaid": "vcenter",
"class": VCenterCredentialForm,
},
CredentialTypes.OPENSHIFT: {
"ouiaid": "openshift",
"class": OpenShiftCredentialForm,
},
CredentialTypes.ANSIBLE: {
"ouiaid": "ansible",
"class": AnsibleCredentialForm,
},
CredentialTypes.RHACS: {
"ouiaid": "rhacs",
"class": RHACSCredentialForm,
},
}

ouiaid, cls = source_type_map.get(source_type).values()
self.open_create_new_modal(type_ouiaid=ouiaid)
return self._new_page(cls)
24 changes: 11 additions & 13 deletions camayoc/ui/models/pages/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from camayoc.ui.enums import Pages
from camayoc.ui.enums import SourceTypes

from ..components.add_new_dropdown import AddNewDropdown
from ..components.form import Form
from ..components.items_list import AbstractListItem
from ..components.popup import PopUp
Expand Down Expand Up @@ -283,8 +284,9 @@ def open_scan(self) -> ScanForm:
return ScanForm(client=self._client)


class SourcesMainPage(MainPageMixin):
class SourcesMainPage(AddNewDropdown, MainPageMixin):
ITEM_CLASS = SourceListElem
ADD_BUTTON_LOCATOR = "button[data-ouia-component-id=add_source_button]"

@service
def add_source(self, data: AddSourceDTO) -> SourcesMainPage:
Expand Down Expand Up @@ -322,37 +324,33 @@ def _add_source_v2(self, data: AddSourceDTO) -> SourcesMainPage:

@record_action
def _open_add_source_v2(self, source_type: SourceTypes) -> SourceCredentialsForm:
create_source_button = "button[data-ouia-component-id=add_source_button]"
source_type_map = {
SourceTypes.NETWORK_RANGE: {
"selector": f"{create_source_button} ~ div ul li[data-ouia-component-id=network]",
"ouiaid": "network",
"class": NetworkRangeSourceCredentialsForm,
},
SourceTypes.SATELLITE: {
"selector": f"{create_source_button} ~ div ul li[data-ouia-component-id=satellite]",
"ouiaid": "satellite",
"class": SatelliteSourceCredentialsForm,
},
SourceTypes.VCENTER_SERVER: {
"selector": f"{create_source_button} ~ div ul li[data-ouia-component-id=vcenter]",
"ouiaid": "vcenter",
"class": VCenterSourceCredentialsForm,
},
SourceTypes.OPENSHIFT: {
"selector": f"{create_source_button} ~ div ul li[data-ouia-component-id=openshift]",
"ouiaid": "openshift",
"class": OpenShiftSourceCredentialsForm,
},
SourceTypes.ANSIBLE_CONTROLLER: {
"selector": f"{create_source_button} ~ div ul li[data-ouia-component-id=ansible]",
"ouiaid": "ansible",
"class": AnsibleSourceCredentialsForm,
},
SourceTypes.RHACS: {
"selector": f"{create_source_button} ~ div ul li[data-ouia-component-id=rhacs]",
"ouiaid": "rhacs",
"class": RHACSSourceCredentialsForm,
},
}

selector, cls = source_type_map.get(source_type).values()

self._driver.click(create_source_button)
self._driver.click(selector)

ouiaid, cls = source_type_map.get(source_type).values()
self.open_create_new_modal(type_ouiaid=ouiaid)
return self._new_page(cls)

0 comments on commit 915059c

Please sign in to comment.