Skip to content

Commit

Permalink
feat - radio and checkbox elements
Browse files Browse the repository at this point in the history
  • Loading branch information
jjpaulo2 committed Aug 3, 2024
1 parent 3f521b3 commit 7084f7d
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 4 deletions.
4 changes: 4 additions & 0 deletions fastrpa/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Element,
InputElement,
FileInputElement,
RadioInputElement,
CheckboxElement,
SelectElement,
ListElement,
ButtonElement,
Expand All @@ -17,6 +19,8 @@
'Element',
'InputElement',
'FileInputElement',
'RadioInputElement',
'CheckboxElement',
'SelectElement',
'ListElement',
'ButtonElement',
Expand Down
14 changes: 11 additions & 3 deletions fastrpa/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
from fastrpa.core.tabs import Tabs
from fastrpa.exceptions import ElementNotCompatibleException
from fastrpa.core.elements import (
CheckboxElement,
Element,
ImageElement,
InputElement,
FileInputElement,
ButtonElement,
FormElement,
ListElement,
RadioInputElement,
TableElement,
SelectElement,
)
Expand Down Expand Up @@ -117,15 +119,21 @@ def input(self, xpath: str, wait: bool = True) -> InputElement:
def file_input(self, xpath: str, wait: bool = True) -> FileInputElement:
return self._specific_element(xpath, FileInputElement, wait)

def radio_input(self, xpath: str, wait: bool = True) -> RadioInputElement:
return self._specific_element(xpath, RadioInputElement, wait)

def checkbox(self, xpath: str, wait: bool = True) -> CheckboxElement:
return self._specific_element(xpath, CheckboxElement, wait)

def select(self, xpath: str, wait: bool = True) -> SelectElement:
return self._specific_element(xpath, SelectElement, wait)

def button(self, xpath: str, wait: bool = True) -> ButtonElement:
return self._specific_element(xpath, ButtonElement, wait)

def form(self, xpath: str, wait: bool = True) -> FormElement:
return self._specific_element(xpath, FormElement, wait)

def select(self, xpath: str, wait: bool = True) -> SelectElement:
return self._specific_element(xpath, SelectElement, wait)

def list(self, xpath: str, wait: bool = True) -> ListElement:
return self._specific_element(xpath, ListElement, wait)

Expand Down
79 changes: 79 additions & 0 deletions fastrpa/core/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,85 @@ def print(self):
print_list(f'{identifier}', self.options)


class RadioInputElement(Element):
@property
def radio_sources(self) -> list[WebElement]:
name = self.attribute('name')
xpath = f'//input[@type="radio"][@name="{name}"][not(@disabled)]'
return find_elements(self.webdriver, xpath)

@property
def options_values(self) -> list[str]:
return [
value
for element in self.radio_sources
if (value := element.get_attribute('value'))
]

@property
def options_labels(self) -> list[str]:
return [
find_element(self.webdriver, xpath).text
for element in self.radio_sources
if (xpath := f'//label[@for="{element.get_attribute("id")}"]')
]

@property
def options(self) -> dict[str, str]:
return {
value: label
for value, label in zip(self.options_values, self.options_labels)
}

def select(self, label: str | None = None, value: str | None = None):
if label:
index = self.options_labels.index(label)
element = self.radio_sources[index]
self.actions.move_to_element(element)
self.actions.click(element)
self.actions.perform()

elif value:
index = self.options_values.index(value)
element = self.radio_sources[index]
self.actions.move_to_element(element)
self.actions.click(element)
self.actions.perform()
else:
raise ValueError('You must provide at least "label" or "value"!')

def has_option(self, label: str | None = None, value: str | None = None):
if label:
return label in self.options_labels
elif value:
return value in self.options_values
raise ValueError('You must provide at least "label" or "value"!')

def __contains__(self, key: Any) -> bool:
return self.has_option(label=key) or self.has_option(value=key)

def print(self):
identifier = f'[@id="{self.id}"]' if self.id else self.xpath
print_list(f'{identifier}', self.options)


class CheckboxElement(Element):

@property
def is_checked(self) -> bool:
return self.source.is_selected()

def check(self):
if not self.is_checked:
self.click()

def uncheck(self):
if self.is_checked:
self.click()

def switch(self):
self.click()

class ListElement(Element):
@property
def items_sources(self) -> list[WebElement]:
Expand Down
18 changes: 18 additions & 0 deletions fastrpa/core/elements_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@

from fastrpa.core.elements import (
ButtonElement,
CheckboxElement,
Element,
FileInputElement,
FormElement,
ImageElement,
InputElement,
ListElement,
RadioInputElement,
SelectElement,
TableElement,
)
Expand Down Expand Up @@ -40,6 +42,22 @@ def element_class(self, element: WebElement) -> Type[Element]:
]
):
return FileInputElement

elif all(
[
element.tag_name == 'input',
element.get_attribute('type') == 'radio',
]
):
return RadioInputElement

elif all(
[
element.tag_name == 'input',
element.get_attribute('type') == 'checkbox',
]
):
return CheckboxElement

elif element.tag_name in ['input', 'textarea']:
return InputElement
Expand Down
2 changes: 1 addition & 1 deletion fastrpa/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def print_list(name: str, values_dict: dict[str | None, str | None]):

rich_tree = Tree(name.replace('[', '\['))
for id, value in values_dict.items():
rich_tree.add(f'[{id}] {value}')
rich_tree.add(f'\[{id}] {value}')
Console().print(rich_tree)

except ImportError:
Expand Down

0 comments on commit 7084f7d

Please sign in to comment.