Skip to content

Commit 8733663

Browse files
committed
feat(robot): port ~8 Playwright keywords for comparison PoC
Add app launcher, form, modal, and related list keywords to SalesforcePlaywright.py using Playwright accessibility selectors.
1 parent 8228da1 commit 8733663

1 file changed

Lines changed: 125 additions & 0 deletions

File tree

cumulusci/robotframework/SalesforcePlaywright.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,131 @@ def _check_for_classic(self):
210210
except AssertionError:
211211
return False
212212

213+
@capture_screenshot_on_error
214+
def open_app_launcher(self, timeout="15 seconds"):
215+
"""Opens the Salesforce App Launcher by clicking the waffle button.
216+
217+
Waits for the App Launcher modal dialog to appear.
218+
"""
219+
self.browser.click("button.slds-icon-waffle_container")
220+
self.wait_until_modal_is_open(timeout=timeout)
221+
222+
@capture_screenshot_on_error
223+
def select_app_launcher_app(self, app_name, timeout="15 seconds"):
224+
"""Searches for and selects an app in the App Launcher.
225+
226+
Requires the App Launcher dialog to already be open.
227+
"""
228+
search_input = "input[placeholder='Search apps and items...']"
229+
self.browser.fill_text(search_input, app_name)
230+
time.sleep(1)
231+
self.browser.click(f"a.slds-app-launcher__tile--small:has-text('{app_name}')")
232+
self.wait_until_loading_is_complete()
233+
234+
@capture_screenshot_on_error
235+
def select_app_launcher_tab(self, tab_name, timeout="15 seconds"):
236+
"""Searches for and selects a tab/item in the App Launcher.
237+
238+
Requires the App Launcher dialog to already be open.
239+
"""
240+
search_input = "input[placeholder='Search apps and items...']"
241+
self.browser.fill_text(search_input, tab_name)
242+
time.sleep(1)
243+
self.browser.click(f"one-app-launcher-menu-item a:has-text('{tab_name}')")
244+
self.wait_until_loading_is_complete()
245+
246+
@capture_screenshot_on_error
247+
def populate_field(self, name, value):
248+
"""Finds a form field by its label and fills it with the given value.
249+
250+
``name`` is the label text of the field.
251+
``value`` is the text to enter.
252+
"""
253+
input_el = f"lightning-input label:has-text('{name}')"
254+
try:
255+
self.browser.get_element(input_el)
256+
self.browser.fill_text(
257+
f"lightning-input:has(label:has-text('{name}')) input", value
258+
)
259+
return
260+
except (AssertionError, Exception):
261+
pass
262+
263+
textarea_el = f"lightning-textarea:has(label:has-text('{name}')) textarea"
264+
try:
265+
self.browser.get_element(textarea_el)
266+
self.browser.fill_text(textarea_el, value)
267+
return
268+
except (AssertionError, Exception):
269+
pass
270+
271+
generic = f"label:has-text('{name}')"
272+
self.browser.get_element(generic)
273+
self.browser.fill_text(
274+
f":near({generic}) input, :near({generic}) textarea", value
275+
)
276+
277+
@capture_screenshot_on_error
278+
def populate_form(self, **kwargs):
279+
"""Fills in multiple form fields at once.
280+
281+
Each keyword argument maps a field label to its desired value.
282+
283+
Example::
284+
285+
Populate Form First Name=Alice Last Name=Smith
286+
"""
287+
for name, value in kwargs.items():
288+
self.populate_field(name, value)
289+
290+
@capture_screenshot_on_error
291+
def click_modal_button(self, button_text, timeout="15 seconds"):
292+
"""Clicks a button with the given text inside the currently open modal dialog.
293+
294+
Waits for the modal to be present first.
295+
"""
296+
self.wait_until_modal_is_open(timeout=timeout)
297+
self.browser.click(
298+
f"div.slds-modal__container button:has-text('{button_text}')"
299+
)
300+
301+
@capture_screenshot_on_error
302+
def wait_until_modal_is_open(self, timeout="15 seconds"):
303+
"""Waits until a Salesforce modal dialog (``slds-modal``) is visible."""
304+
self.browser.wait_for_elements_state("section.slds-modal", "visible", timeout)
305+
306+
@capture_screenshot_on_error
307+
def wait_until_modal_is_closed(self, timeout="15 seconds"):
308+
"""Waits until all Salesforce modal dialogs (``slds-modal``) have disappeared."""
309+
self.browser.wait_for_elements_state("section.slds-modal", "detached", timeout)
310+
311+
@capture_screenshot_on_error
312+
def click_related_list_button(self, heading, button_title):
313+
"""Clicks a button within a related list identified by its heading.
314+
315+
``heading`` is the title text of the related list (e.g. "Contacts").
316+
``button_title`` is the visible text of the button to click.
317+
"""
318+
card = f"article.slds-card:has(span[title='{heading}'])"
319+
self.browser.click(f"{card} button:has-text('{button_title}')")
320+
321+
@capture_screenshot_on_error
322+
def get_related_list_count(self, heading):
323+
"""Returns the item count displayed in a related list's heading.
324+
325+
``heading`` is the title of the related list (e.g. "Contacts").
326+
Returns the integer count parsed from the heading, or 0 if no
327+
count is found.
328+
"""
329+
span_text = self.browser.get_text(
330+
f"article.slds-card:has(span[title='{heading}']) "
331+
f"span.slds-card__header-title"
332+
)
333+
match = re.search(r"\((\d+)\)", span_text)
334+
if match:
335+
return int(match.group(1))
336+
return 0
337+
213338
def breakpoint(self):
214339
"""Serves as a breakpoint for the robot debugger
215340

0 commit comments

Comments
 (0)