Skip to content

Commit

Permalink
Refactored Bookmark
Browse files Browse the repository at this point in the history
Moved all bookmark functionalities into a single class, Bookmark
  • Loading branch information
Temidayo32 committed Dec 19, 2024
1 parent 8400326 commit 30d118e
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 290 deletions.
68 changes: 68 additions & 0 deletions foxpuppet/region.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException
from foxpuppet.windows import BaseWindow
from typing import Tuple


class Region(object):
Expand Down Expand Up @@ -38,3 +41,68 @@ def __init__(self, window: BaseWindow, root: WebElement):
self.selenium: WebDriver = window.selenium
self.wait: WebDriverWait = window.wait
self.window: BaseWindow = window
self.actions: ActionChains = ActionChains(self.selenium)

def click_element(self, locator: Tuple[str, str]) -> None:
"""Click on an element by its locator."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.find_element(locator).click()

def find_element(self, locator: Tuple[str, str]) -> WebElement:
"""Find and return a web element by its locator."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
try:
element = self.root.find_element(*locator)
return element
except Exception as e:
raise NoSuchElementException(
f"Error locating element with locator {locator}: {e}"
)

def context_click(self, locator: Tuple[str, str]) -> None:
"""
Perform a right-click (context-click) on an element.
Args:
locator (tuple): Locator for the element to right-click.
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
element = self.find_element(locator)
self.actions.context_click(element).perform()

def switch_to_frame(self, locator: Tuple[str, str]) -> None:
"""
Switch to an iFrame using its locator
Args:
locator (tuple): Locator for the iFrame elemeent.
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
frame_element = self.find_element(locator)
if frame_element is not None:
self.selenium.switch_to.frame(frame_element)
else:
raise NoSuchElementException(f"iFrame with locator {locator} not found.")

def switch_to_default_context(self) -> None:
"""Switch back to default context."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.selenium.switch_to.default_content()

def open_main_menu(
self, locator_toolbar: Tuple[str, str], locator_menu_bar: Tuple[str, str]
) -> None:
"""Activate main menu bar"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.context_click(locator_toolbar)
self.click_element(locator_menu_bar)

def open_bookmark_menu(
self, locator_panel: Tuple[str, str], locator_bookmark: Tuple[str, str]
) -> None:
"""
Opens the Bookmarks menu in Panel UI
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.click_element(locator_panel)
self.click_element(locator_bookmark)
123 changes: 48 additions & 75 deletions foxpuppet/windows/browser/bookmarks/bookmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,29 @@ class BookmarkData(TypedDict):
keyword: Optional[str]


class BasicBookmark(NavBar):
"""Handles basic bookmark operations."""
class Bookmark(NavBar):
"""Handles Bookmark operations in Firefox."""

if TYPE_CHECKING:
from foxpuppet.windows.browser.window import BrowserWindow

@staticmethod
def create(window: "BrowserWindow", root: WebElement) -> Optional["BasicBookmark"]:
def create(window: "BrowserWindow", root: WebElement) -> "Bookmark":
"""Create a bookmark object.
Args:
window (:py:class:`BrowserWindow`): Window object this bookmark appears in
root (:py:class:`~selenium.webdriver.remote.webelement.WebElement`): WebDriver element object for bookmark
Returns:
:py:class:`BaseBookmark`: Bookmark instance or None
:py:class:`Bookmark`: Bookmark instance
"""
with window.selenium.context(window.selenium.CONTEXT_CHROME):
try:
return BasicBookmark(window, root)
except NoSuchElementException:
return None
return Bookmark(window, root)

@property
def is_bookmarked(self) -> bool:
"""Checks if the current page is bookmarked.
def is_bookmarked_star(self) -> bool:
"""Checks if the current page is bookmarked using the star button.
Returns:
bool: True if the page is bookmarked, False otherwise.
Expand All @@ -54,72 +51,9 @@ def is_bookmarked(self) -> bool:
star_button_image = self.find_element(BookmarkLocators.STAR_BUTTON_IMAGE)
return star_button_image.get_attribute("starred") == "true"

def add(self) -> None:
"""Add a Bookmark using the star button."""
self.click_element(BookmarkLocators.STAR_BUTTON)
self.click_element(BookmarkLocators.FOLDER_MENU)
self.click_element(BookmarkLocators.OTHER_BOOKMARKS_STAR)
self.click_element(BookmarkLocators.SAVE_BUTTON)

def retrieve_bookmark(self, label: str) -> bool:
"""
Check if a bookmark with the given label exists.
Args:
label (str): The name of the bookmark to search for.
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.open_bookmark_menu(
locator_panel=BookmarkLocators.PANEL_MENU,
locator_bookmark=BookmarkLocators.PANEL_BOOKMARK_MENU,
)
panel_bookmarks = self.find_element(BookmarkLocators.PANEL_BOOKMARK_TOOLBAR)
if panel_bookmarks is not None:
menu_items = panel_bookmarks.find_elements(
By.CSS_SELECTOR, "toolbarbutton.bookmark-item"
)
if menu_items is not None:
for item in menu_items:
item_label = item.get_attribute("label")
if item_label and label.lower() in item_label.lower():
return True
return False

def delete(self) -> None:
"""Delete a bookmark using the star button."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
star_button_image = self.find_element(BookmarkLocators.STAR_BUTTON_IMAGE)
if star_button_image and star_button_image.get_attribute("starred") == "true":
self.click_element(BookmarkLocators.STAR_BUTTON)
self.click_element(BookmarkLocators.REMOVE_BUTTON)


class AdvancedBookmark(BasicBookmark):
"""Handles advanced bookmark operations."""

if TYPE_CHECKING:
from foxpuppet.windows.browser.window import BrowserWindow

@staticmethod
def create(window: "BrowserWindow", root: WebElement) -> Optional["AdvancedBookmark"]:
"""Create an advanced bookmark object.
Args:
window (:py:class:`BrowserWindow`): The window object where the bookmark appears.
root (:py:class:`~selenium.webdriver.remote.webelement.WebElement`): WebElement for the bookmark panel.
Returns:
:py:class:`AdvancedBookmark`: An instance of AdvancedBookmark if successful, otherwise None.
"""
with window.selenium.context(window.selenium.CONTEXT_CHROME):
try:
return AdvancedBookmark(window, root)
except NoSuchElementException:
return None

@property
def is_bookmarked(self) -> bool:
"""Checks if the current page is bookmarked.
def is_bookmarked_menu(self) -> bool:
"""Checks if the current page is bookmarked using the main bookmark menu.
Returns:
bool: True if the page is bookmarked, False otherwise.
Expand All @@ -142,6 +76,13 @@ def is_bookmarked(self) -> bool:
return True
return False

def add(self) -> None:
"""Add a Bookmark using the star button."""
self.click_element(BookmarkLocators.STAR_BUTTON)
self.click_element(BookmarkLocators.FOLDER_MENU)
self.click_element(BookmarkLocators.OTHER_BOOKMARKS_STAR)
self.click_element(BookmarkLocators.SAVE_BUTTON)

def add_bookmark(self, bookmark_data: BookmarkData) -> None:
"""Add a Bookmark using the main bookmark menu."""
self.open_main_menu(
Expand Down Expand Up @@ -177,6 +118,38 @@ def add_bookmark(self, bookmark_data: BookmarkData) -> None:
self.actions.send_keys(Keys.TAB, Keys.ENTER).perform()
self.switch_to_default_context()

def retrieve_bookmark(self, label: str) -> bool:
"""
Check if a bookmark with the given label exists.
Args:
label (str): The name of the bookmark to search for.
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.open_bookmark_menu(
locator_panel=BookmarkLocators.PANEL_MENU,
locator_bookmark=BookmarkLocators.PANEL_BOOKMARK_MENU,
)
panel_bookmarks = self.find_element(BookmarkLocators.PANEL_BOOKMARK_TOOLBAR)
if panel_bookmarks is not None:
menu_items = panel_bookmarks.find_elements(
By.CSS_SELECTOR, "toolbarbutton.bookmark-item"
)
if menu_items is not None:
for item in menu_items:
item_label = item.get_attribute("label")
if item_label and label.lower() in item_label.lower():
return True
return False

def delete(self) -> None:
"""Delete a bookmark using the star button."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
star_button_image = self.find_element(BookmarkLocators.STAR_BUTTON_IMAGE)
if star_button_image and star_button_image.get_attribute("starred") == "true":
self.click_element(BookmarkLocators.STAR_BUTTON)
self.click_element(BookmarkLocators.REMOVE_BUTTON)

def delete_bookmark(self, label: str) -> bool:
"""Delete a bookmark using the main bookmark menu."""
self.open_main_menu(
Expand Down
74 changes: 1 addition & 73 deletions foxpuppet/windows/browser/navbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
"""Creates Navbar object to interact with Firefox Navigation Bar."""

from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException
from foxpuppet.region import Region
from typing import Tuple, Optional
from typing import Tuple
from foxpuppet.windows.base import BaseWindow


Expand All @@ -30,10 +26,6 @@ class NavBar(Region):
"tracking-protection-icon-box",
)

def __init__(self, window: BaseWindow, root: WebElement) -> None:
super().__init__(window, root)
self.actions: ActionChains = ActionChains(self.selenium)

@property
def is_tracking_shield_displayed(self) -> bool:
"""Tracking Protection shield.
Expand All @@ -48,67 +40,3 @@ def is_tracking_shield_displayed(self) -> bool:
return el.get_attribute("active") is not None
el = self.root.find_element(By.ID, "tracking-protection-icon")
return bool(el.get_attribute("state"))

def click_element(self, locator: Tuple[str, str]) -> None:
"""Click on an element by its locator."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.find_element(locator).click()

def find_element(self, locator: Tuple[str, str]) -> WebElement:
"""Find and return a web element by its locator."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
try:
element = self.root.find_element(*locator)
return element
except Exception as e:
raise NoSuchElementException(
f"Error locating element with locator {locator}: {e}"
)

def context_click(self, locator: Tuple[str, str]) -> None:
"""
Perform a right-click (context-click) on an element.
Args:
locator (tuple): Locator for the element to right-click.
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
element = self.find_element(locator)
self.actions.context_click(element).perform()

def switch_to_frame(self, locator: Tuple[str, str]) -> None:
"""
Switch to an iFrame using its locator
Args:
locator (tuple): Locator for the iFrame elemeent.
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
frame_element = self.find_element(locator)
if frame_element is not None:
self.selenium.switch_to.frame(frame_element)
else:
raise NoSuchElementException(f"iFrame with locator {locator} not found.")

def switch_to_default_context(self) -> None:
"""Switch back to default context."""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.selenium.switch_to.default_content()

def open_main_menu(
self, locator_toolbar: Tuple[str, str], locator_menu_bar: Tuple[str, str]
) -> None:
"""Activate main menu bar"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.context_click(locator_toolbar)
self.click_element(locator_menu_bar)

def open_bookmark_menu(
self, locator_panel: Tuple[str, str], locator_bookmark: Tuple[str, str]
) -> None:
"""
Opens the Bookmarks menu in Panel UI
"""
with self.selenium.context(self.selenium.CONTEXT_CHROME):
self.click_element(locator_panel)
self.click_element(locator_bookmark)
Loading

0 comments on commit 30d118e

Please sign in to comment.