Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion SELECTOR_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,14 @@ Description: The Firefox logo
Location: The about:newtab page
Path to .json: modules/data/about_newtab.components.json
```
```
Selector Name: top-site-by-title
Selector Data: "//li[@class='top-site-outer']//span[@class='title-label' and text()='{title}']/.."
Description: Topsite tile by title
Location: The about:newtab page (middle section)
Path to .json: modules/data/about_newtab.components.json
```

#### about_prefs
```
Selector Name: search-engine-dropdown-root
Expand Down Expand Up @@ -1830,6 +1838,20 @@ Description: Context menu option to move a tab to the start of the tab bar.
Location: Context menu - Tab
Path to .json: modules/data/context_menu.components.json
```
```
Selector Name: context-menu-bookmark-link
Selector Data: context-bookmarklink
Description: Context menu option to bookmark a link
Location: Context menu - topsite context menu
Path to .json: modules/data/context_menu.components.json
```
```
Selector Name: context-menu-search-select
Selector Data: coontext-searchselect
Description: Context menu option to search selected text with the engine set as default
Location: Context menu - topsite context menu
Path to .json: modules/data/context_menu.components.json
```
#### credit_card_fill
```
Selector Name: form-field
Expand Down Expand Up @@ -3132,6 +3154,13 @@ Description: Developer tool icon
Location: Navigation bar
Path to .json: modules/data/navigation.components.json
```
```
Selector Name: status-panel-label
Selector Data: statuspanel-label
Description: Status panel URL label
Location: newtab page bottom left corner on link hover
Path to .json: modules/data/navigation.components.json
```
#### panel_ui
```
Selector name: panel-ui-button
Expand Down Expand Up @@ -3509,7 +3538,7 @@ Description: Edit bookmark panel
Location: Bookmark panel
Path to .json: modules/data/pane_ui.components.json
```
```

#### print_preview
```
Selector name: print-preview-browser
Expand Down
44 changes: 40 additions & 4 deletions modules/browser_object_context_menu.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from typing import Union
from typing import Dict, List, Union

from selenium.webdriver.remote.webelement import WebElement

Expand All @@ -13,15 +13,51 @@ class ContextMenu(BasePage):

URL_TEMPLATE = ""

@BasePage.context_chrome
def click_context_item(
self, reference: Union[str, tuple, WebElement], labels=[]
) -> BasePage:
"""
Clicks the context item.
"""
with self.driver.context(self.driver.CONTEXT_CHROME):
self.fetch(reference, labels=labels).click()
return self

self.fetch(reference, labels=labels).click()
return self

@BasePage.context_chrome
def verify_topsites_tile_context_menu_options(
self,
static_items: Dict[str, str],
dynamic_items: List[str],
tile_title: str,
):
"""
Verifies expected context menu options are present upon right clicking a topsite tile.
Arguments:
static_items: Dict mapping of selector name to expected label text.
dynamic_items: List of selector names for items with dynamic labels.
tile_title: Optional, required if dynamic label validation is needed (e.g., Wikipedia, YouTube).
"""
# --- Static items ---
for selector, expected_label in static_items.items():
option = self.get_element(selector)
label = (option.get_attribute("label") or option.text or "").strip()
assert expected_label in label, (
f'Expected label "{expected_label}" not found. Got: "{label}"'
)

# --- Dynamic items ---
for selector in dynamic_items:
option = self.get_element(selector)
label = (option.get_attribute("label") or option.text or "").strip()
normalized = label.lower()
assert normalized.startswith("search"), (
f'Label does not start with "Search": "{label}"'
)
assert "for" in normalized, f'"for" not found in label: "{label}"'
assert tile_title.lower() in normalized, (
f'Search term "{tile_title}" not found in label: "{label}"'
)


class AboutDownloadsContextMenu(ContextMenu):
Expand Down
23 changes: 22 additions & 1 deletion modules/browser_object_navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Navigation(BasePage):
"Bing",
"DuckDuckGo",
"Wikipedia (en)",
"Firefox Add-ons"
"Firefox Add-ons",
}

def __init__(self, driver: Firefox, **kwargs):
Expand Down Expand Up @@ -751,3 +751,24 @@ def verify_autoplay_state(self, expected: Literal["allow", "block"]) -> None:
else:
self.element_visible("permission-popup-audio-video-blocked")
self.element_visible("autoplay-icon-blocked")

@BasePage.context_chrome
def get_status_panel_url(self) -> str:
"""
Gets the URL displayed in the status panel at the bottom left of the browser.
"""
self.element_visible("status-panel-label")
status_label = self.get_element("status-panel-label")
url = status_label.get_attribute("value")
return url

def verify_status_panel_url(self, expected_url: str):
"""
Verify that the browser status panel (browser's bottom-left) contains the expected URL.
Argument:
expected_url: The expected URL substring to be found in the status panel
"""
actual_url = self.get_status_panel_url()
assert expected_url in actual_url, (
f"Expected '{expected_url}' in status panel URL, got '{actual_url}'"
)
8 changes: 7 additions & 1 deletion modules/data/about_newtab.components.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,11 @@
"selectorData": "logo",
"strategy": "class",
"groups": []
}
},

"top-site-by-title": {
"selectorData": "//li[@class='top-site-outer']//span[@class='title-label' and text()='{title}']/..",
"strategy": "xpath",
"groups": []
}
}
13 changes: 13 additions & 0 deletions modules/data/context_menu.components.json
Original file line number Diff line number Diff line change
Expand Up @@ -221,5 +221,18 @@
"selectorData": "placesContext_openBookmarkContainer:tabs",
"strategy": "id",
"groups": []
},

"context-menu-bookmark-link": {
"selectorData": "context-bookmarklink",
"strategy": "id",
"groups": []
},

"context-menu-search-select": {
"selectorData": "context-searchselect",
"strategy": "id",
"groups": []
}

}
6 changes: 6 additions & 0 deletions modules/data/navigation.components.json
Original file line number Diff line number Diff line change
Expand Up @@ -603,5 +603,11 @@
"selectorData": "developer-button",
"strategy": "id",
"groups": []
},

"status-panel-label": {
"selectorData": "statuspanel-label",
"strategy": "id",
"groups": []
}
}
17 changes: 17 additions & 0 deletions modules/page_object_newtab.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,20 @@ def check_layout(self) -> BasePage:
logging.info(f"Found {self.count_top_sites()} top sites")
# ODD: Sometimes we get 7 top sites, not 8
assert self.count_top_sites() in self.TOP_SITES_TOTAL

@BasePage.context_content
def get_topsite_element(self, tile_title: str):
"""Get a topsite tile element by title."""
return self.get_element("top-site-by-title", labels=[tile_title])

@BasePage.context_content
def open_topsite_context_menu_by_title(self, tile_title: str):
"""
Opens the context menu for a topsite tile by its title.
Argument:
tile_title: The title text of the tile (eg. "Wikipedia")
"""
# Get the tile by title and right-click on it to open context menu
tile = self.get_topsite_element(tile_title)
self.context_click(tile)
return self
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import pytest
from selenium.webdriver import Firefox

from modules.browser_object_context_menu import ContextMenu
from modules.browser_object_navigation import Navigation
from modules.browser_object_tabbar import TabBar
from modules.page_object_generics import GenericPage
from modules.page_object_newtab import AboutNewtab


@pytest.fixture()
def test_case():
return "3029116"


STATIC_CONTEXT_MENU_OPTIONS = {
"context-menu-open-link-in-tab": "Open Link in New Tab",
"context-menu-open-link-in-new-window": "Open Link in New Window",
"context-menu-open-link-in-new-private-window": "Open Link in New Private Window",
"context-menu-bookmark-link": "Bookmark Link",
"context-menu-save-link": "Save Link As",
"context-menu-copy-link": "Copy Link",
"context-menu-inspect": "Inspect",
}

DYNAMIC_CONTEXT_MENU_ITEMS = ["context-menu-search-select"]

TOPSITE_TITLE = "Wikipedia"
TOPSITE_URL = "www.wikipedia.org"


def test_non_sponsored_topsite_context_menu_option(driver: Firefox) -> None:
"""
C3029116 - Verifies that the browser's context menu displays the expected options
when right-clicking a top site tile, and that the opened link matches the
status panel URL shown on hover.
"""
tabs = TabBar(driver)
newtab = AboutNewtab(driver)
context_menu = ContextMenu(driver)
nav = Navigation(driver)
page = GenericPage(driver, url="about:newtab")

# Open about:newtab and hover over the desired TOPSITE_TITLE tile and verify status panel URL (bottom-left)
page.open()
title_element = newtab.get_topsite_element(TOPSITE_TITLE)
newtab.hover(title_element)
nav.verify_status_panel_url(TOPSITE_URL)
status_panel_url = nav.get_status_panel_url()

# Right-click to open context menu
newtab.open_topsite_context_menu_by_title(TOPSITE_TITLE)

# Verify context menu options
context_menu.verify_topsites_tile_context_menu_options(
STATIC_CONTEXT_MENU_OPTIONS,
DYNAMIC_CONTEXT_MENU_ITEMS,
TOPSITE_TITLE,
)

# Click first option and verify link opens in new tab
context_menu.click_context_item("context-menu-open-link-in-tab")
tabs.switch_to_new_tab()
nav.url_contains(status_panel_url)