Skip to content

Commit 0e4dab9

Browse files
authored
Merge pull request #95 from mozilla/sl/tile-menu-options
Tile Options (new tab)
2 parents 5128614 + e886c6e commit 0e4dab9

File tree

5 files changed

+232
-2
lines changed

5 files changed

+232
-2
lines changed

modules/data/navigation.components.json

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,5 +160,29 @@
160160
"groups": [
161161
"doNotCache"
162162
]
163+
},
164+
165+
"sponsored-site-card": {
166+
"selectorData": "top-site-outer",
167+
"strategy": "class",
168+
"groups": []
169+
},
170+
171+
"sponsored-site-card-menu-button": {
172+
"selectorData": "button[class=\"context-menu-button icon\"]",
173+
"strategy": "css",
174+
"groups": []
175+
},
176+
177+
"sponsored-site-context-menu": {
178+
"selectorData": "context-menu",
179+
"strategy": "class",
180+
"groups": []
181+
},
182+
183+
"sponsored-site-context-menu-list": {
184+
"selectorData": "ul[class=\"context-menu-list\"]",
185+
"strategy": "css",
186+
"groups": []
163187
}
164-
}
188+
}

modules/util.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import re
77
from os import remove
88
from random import shuffle
9-
from typing import Literal, Union
9+
from typing import List, Literal, Union
1010

1111
from faker import Faker
1212
from faker.providers import internet, misc
@@ -266,6 +266,56 @@ def fake_credit_card_data(self) -> CreditCardBase:
266266

267267
return fake_data
268268

269+
def write_css_properties(
270+
self, file_path: str, element: WebElement, driver: Firefox, chrome=False
271+
):
272+
"""
273+
Executes JavaScript to get all of the CSS properties of a WebElement then dumps it in the specified file path location. Outputs in JSON format
274+
"""
275+
css_properties = ""
276+
if chrome:
277+
with driver.context(driver.CONTEXT_CHROME):
278+
css_properties = driver.execute_script(
279+
"""
280+
var s = window.getComputedStyle(arguments[0]);
281+
var props = {};
282+
for (var i = 0; i < s.length; i++) {
283+
props[s[i]] = s.getPropertyValue(s[i]);
284+
}
285+
return props;
286+
""",
287+
element,
288+
)
289+
290+
else:
291+
css_properties = driver.execute_script(
292+
"""
293+
var s = window.getComputedStyle(arguments[0]);
294+
var props = {};
295+
for (var i = 0; i < s.length; i++) {
296+
props[s[i]] = s.getPropertyValue(s[i]);
297+
}
298+
return props;
299+
""",
300+
element,
301+
)
302+
303+
with open(file_path, "w") as file:
304+
json.dump(css_properties, file, indent=4)
305+
logging.info(f"CSS properties saved to {file_path}")
306+
307+
def match_regex(self, pattern: str, to_match: List[str]) -> List[str]:
308+
"""
309+
Given a list of logs/strings, this method will return the matches within the string that match the given regex expression.
310+
"""
311+
matches = []
312+
for string in to_match:
313+
match = re.findall(pattern, string)
314+
if len(match) > 0:
315+
matches.append(match[0])
316+
317+
return matches
318+
269319
def normalize_phone_number(self, phone: str, default_country_code="1") -> str:
270320
"""
271321
Given a phone number in some format, +1(xxx)-xxx-xxxx or something similar, it will strip the phone number

tests/address_bar_and_search/conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ def set_prefs(add_prefs: dict):
2020
("privacy.donottrackheader.enabled", False),
2121
("telemetry.fog.test.localhost_port", 5312),
2222
("datareporting.healthreport.uploadEnabled", True),
23+
("browser.newtabpage.enabled", True),
24+
("browser.newtabpage.activity-stream.system.showSponsored", True),
25+
("browser.newtabpage.activity-stream.showSponsoredTopSites", True),
26+
("browser.topsites.useRemoteSetting", True),
27+
("browser.topsites.contile.enabled", True),
2328
]
2429
prefs.extend(add_prefs)
2530
return prefs
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import logging
2+
3+
import pytest
4+
from selenium.webdriver import Firefox
5+
6+
from modules.browser_object import TabBar
7+
from modules.page_object import Navigation
8+
from modules.util import Utilities
9+
10+
ALLOWED_RGB_BEFORE_VALUES_CARD = set(["rgba(0, 0, 0, 0)"])
11+
ALLOWED_RGB_AFTER_VALUES_CARD = set(
12+
["color(srgb 0.878824 0.878824 0.885882)", "color(srgb 0.334902 0.331765 0.36)"]
13+
)
14+
ALLOWED_RGB_VALUES_BEFORE_THREE_DOTS = set(
15+
[
16+
"color(srgb 0.356863 0.356863 0.4 / 0.07)",
17+
"color(srgb 0.984314 0.984314 0.996078 / 0.07)",
18+
]
19+
)
20+
ALLOWED_RGB_AFTER_VALUES_THREE_DOTS = set(
21+
[
22+
"color(srgb 0.356863 0.356863 0.4 / 0.14)",
23+
"color(srgb 0.984314 0.984314 0.996078 / 0.14)",
24+
]
25+
)
26+
27+
REQUIRED_CONTEXT_MENU_ACTIONS_REGULAR_TILE = set(
28+
["Pin", "Edit", "Open in a New Window", "Open in a New Private Window", "Dismiss"]
29+
)
30+
31+
REQUIRED_CONTEXT_MENU_ACTIONS_SPONSORED_TILE = set(
32+
[
33+
"Open in a New Window",
34+
"Open in a New Private Window",
35+
"Dismiss",
36+
"Our sponsors &amp; your privacy",
37+
]
38+
)
39+
40+
# first value in a tuple is the index of the card, second is the status of sponsorship
41+
card_indices = [(3, False), (0, True)]
42+
43+
44+
@pytest.fixture()
45+
def add_prefs():
46+
return [
47+
("browser.search.region", "US"),
48+
]
49+
50+
51+
def test_default_tile_hover_states(driver: Firefox):
52+
"""
53+
C1533798.1: Ensure that hover states work correctly
54+
"""
55+
# instantiate objects
56+
nav = Navigation(driver).open()
57+
tabs = TabBar(driver)
58+
59+
# open a new tab and switch to it
60+
tabs.new_tab_by_button()
61+
tabs.wait_for_num_tabs(2)
62+
driver.switch_to.window(driver.window_handles[-1])
63+
top_card = nav.get_element("sponsored-site-card")
64+
65+
# assert the hover state
66+
assert (
67+
top_card.value_of_css_property("background-color")
68+
in ALLOWED_RGB_BEFORE_VALUES_CARD
69+
)
70+
tabs.hover_over_element(top_card)
71+
assert (
72+
top_card.value_of_css_property("background-color")
73+
in ALLOWED_RGB_AFTER_VALUES_CARD
74+
)
75+
76+
three_dot_menu = nav.get_element("sponsored-site-card-menu-button")
77+
78+
# assert the hover state again for the three dots
79+
assert (
80+
three_dot_menu.value_of_css_property("background-color")
81+
in ALLOWED_RGB_VALUES_BEFORE_THREE_DOTS
82+
)
83+
tabs.hover_over_element(three_dot_menu)
84+
assert (
85+
three_dot_menu.value_of_css_property("background-color")
86+
in ALLOWED_RGB_AFTER_VALUES_THREE_DOTS
87+
)
88+
89+
90+
@pytest.mark.parametrize("index, sponsored", card_indices)
91+
def test_tile_context_menu_options(driver: Firefox, index: int, sponsored: bool):
92+
"""
93+
C1533798.2: Ensure that a website has the appropriate context menu actions in the tile.
94+
"""
95+
# initialize objects
96+
nav = Navigation(driver).open()
97+
tabs = TabBar(driver)
98+
util = Utilities()
99+
100+
# open a new tab, switch to it and get the sponsored card
101+
tabs.new_tab_by_button()
102+
tabs.wait_for_num_tabs(2)
103+
driver.switch_to.window(driver.window_handles[-1])
104+
suggested_cards = nav.get_element("sponsored-site-card", multiple=True)
105+
106+
# pick the fourth card since it is not a sponsored tile
107+
card = suggested_cards[index]
108+
nav.hover_over_element(card)
109+
110+
# press the three dots option
111+
three_dot_menu = nav.get_element(
112+
"sponsored-site-card-menu-button", parent_element=card
113+
)
114+
three_dot_menu.click()
115+
116+
# get all of the context menu actions
117+
context_menu_list = nav.get_element("sponsored-site-context-menu-list")
118+
child_options = nav.get_all_children(context_menu_list)
119+
logging.info(f"There are {len(child_options)} context options")
120+
121+
# match appropriate regex to extract the word of the context menu option
122+
option_html_logs = [
123+
option.get_attribute("innerHTML")
124+
for option in child_options
125+
if option.get_attribute("innerHTML") != ""
126+
]
127+
128+
matched_regex = util.match_regex(
129+
r"<button[^>]*><span[^>]*>([^<]*)</span></button>", option_html_logs
130+
)
131+
132+
# according to the status of sponsored, look at different context menu actions
133+
set_in_use = set()
134+
if sponsored:
135+
set_in_use = REQUIRED_CONTEXT_MENU_ACTIONS_SPONSORED_TILE
136+
else:
137+
set_in_use = REQUIRED_CONTEXT_MENU_ACTIONS_REGULAR_TILE
138+
139+
# ensure we match each option
140+
for match in matched_regex:
141+
if match in set_in_use:
142+
set_in_use.remove(match)
143+
logging.info(f"Detected the context item: {match}")
144+
145+
assert (
146+
len(set_in_use) == 0
147+
), "Did not find all of the required context menu actions."

tests/pocket/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ def set_prefs(add_prefs: dict):
3333
("browser.newtabpage.activity-stream.feeds.system.topstories", True),
3434
("browser.newtabpage.activity-stream.showSponsoredTopSites", True),
3535
("browser.ping-centre.log", True),
36+
(
37+
"services.sync.prefs.sync.browser.newtabpage.activity-stream.showSponsoredTopSites",
38+
True,
39+
),
3640
]
3741
prefs.extend(add_prefs)
3842
return prefs

0 commit comments

Comments
 (0)