Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ For example:
* Ben French (BenjaminFrench)
* Rupert Barrow (rupertbarrow)
* Rupesh J (rupeshjSFDC)
* Bhimeswara Vamsi Punnam (b-vamsipunnam)
62 changes: 62 additions & 0 deletions cumulusci/robotframework/Salesforce.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,65 @@ def select_window(self, locator="MAIN", timeout=None):
"'Select Window' is deprecated; use 'Switch Window' instead", "WARN"
)
self.selenium.switch_window(locator=locator, timeout=timeout)

@capture_screenshot_on_error
def get_all_picklist_values(self, picklist, timeout="10s"):
"""Return all available values from a Salesforce Lightning picklist.

Opens the picklist identified by its visible field label and returns
the option values currently rendered in the Lightning picklist.

Required field labels are supported. For example, ``Status``,
``Status *``, and ``*Status`` can be matched.

Examples:
| ${values}= | Get All Picklist Values | Status |
| ${values}= | Get All Picklist Values | Lead Status | timeout=15s |
"""
label_xpath = (
f"//label["
f"normalize-space(.)='{picklist}' "
f"or normalize-space(.)='{picklist} *' "
f"or normalize-space(.)='*{picklist}'"
f"]"
)

option_xpath = (
f"{label_xpath}"
"/ancestor::*[contains(@class,'slds-form-element')]"
"//lightning-base-combobox-item"
"//span[contains(@class,'slds-media__body') or @slot='label']"
)

try:
self.selenium.set_focus_to_element(label_xpath)
self.scroll_element_into_view(label_xpath)
self.selenium.click_element(label_xpath)
self.selenium.wait_until_element_is_visible(option_xpath, timeout=timeout)

values = []
for element in self.selenium.get_webelements(option_xpath):
try:
values.append(element.text.strip())
except (StaleElementReferenceException, WebDriverException):
continue

self.builtin.log(
f"Retrieved {len(values)} values from picklist '{picklist}'.",
"INFO",
)
return values

except ElementNotFound:
raise AssertionError(
f"Picklist '{picklist}' was not found on the page."
) from None

finally:
try:
self.selenium.press_keys(None, "ESC")
except Exception as err:
self.builtin.log(
f"Failed to close picklist dropdown: {err}",
"DEBUG",
)
63 changes: 63 additions & 0 deletions cumulusci/robotframework/tests/salesforce/picklist.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
*** Settings ***
Documentation
... This suite tests the `Get All Picklist Values` keyword.
... Specifically, it verifies that the keyword can open a Salesforce
... Lightning picklist and return the available option values.

Library String
Library DateTime
Library Collections
Resource cumulusci/robotframework/Salesforce.robot

Suite Setup run keywords
... Open test browser
... AND Create opportunity
Suite Teardown Delete Records and Close Browser


*** Keywords ***
Create opportunity
[Documentation]
... Creates a test opportunity with a random name and a close
... date 30 days in the future. A reference to the created
... opportunity will be stored in the suite variable ${opportunity}.

${30 days from now}= Get Current Date increment=30 days result_format=%Y-%m-%d
${random}= Generate random string 8 [NUMBERS]
${opportunity_id}= Salesforce Insert Opportunity
... Name=Picklist Test ${random}
... CloseDate=${30 days from now}
... Amount=100000
... Probability=42
... StageName=Prospecting
... Description=Picklist keyword test
&{opportunity}= Salesforce Get Opportunity ${opportunity_id}
set suite variable ${opportunity}
[Return] ${opportunity}


*** Test Cases ***
Test Get All Picklist Values
[Documentation]
... Verify that Get All Picklist Values returns available values
... from a Lightning picklist field.

[Setup] run keywords
... go to object home Opportunity
... AND click link ${opportunity['Name']}
... AND click object button Edit
... AND wait until modal is open

${values}= Get All Picklist Values Stage
Log ${values}

Run keyword and continue on failure
... Should Not Be Empty
... ${values}
... Expected Stage picklist values to be returned but received an empty list

Run keyword and continue on failure
... List Should Contain Value
... ${values}
... Prospecting
... Expected Stage picklist to contain 'Prospecting' but values were '${values}'
66 changes: 66 additions & 0 deletions cumulusci/robotframework/tests/test_salesforce.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from SeleniumLibrary.errors import ElementNotFound

from cumulusci.robotframework.Salesforce import Salesforce
from selenium.common.exceptions import StaleElementReferenceException


# _init_locators has a special code block
Expand Down Expand Up @@ -77,3 +78,68 @@ def setup_class(cls):
def test_breakpoint(self, mock_robot_context):
"""Verify that the keyword doesn't raise an exception"""
assert self.sflib.breakpoint() is None


@mock.patch("robot.libraries.BuiltIn.BuiltIn._get_context")
class TestKeywordGetAllPicklistValues:
@classmethod
def setup_class(cls):
cls.sflib = Salesforce(locators={"body": "//whatever"})

def test_returns_rendered_picklist_values(self, mock_robot_context):
option_1 = mock.Mock(text="Warm")
option_2 = mock.Mock(text="Cold")
option_3 = mock.Mock(text="Warm")
option_4 = mock.Mock(text=" ")

with mock.patch.object(self.sflib, "scroll_element_into_view"):
self.sflib.selenium.get_webelements.return_value = [
option_1,
option_2,
option_3,
option_4,
]

values = self.sflib.get_all_picklist_values("Status")

assert values == ["Warm", "Cold", "Warm", ""]
self.sflib.selenium.wait_until_element_is_visible.assert_called_once()
self.sflib.selenium.press_keys.assert_any_call(None, "ESC")

def test_ignores_stale_options(self, mock_robot_context):
good_option = mock.Mock(text="Active")

stale_option = mock.Mock()
type(stale_option).text = mock.PropertyMock(
side_effect=StaleElementReferenceException()
)

with mock.patch.object(self.sflib, "scroll_element_into_view"):
self.sflib.selenium.get_webelements.return_value = [
stale_option,
good_option,
]

values = self.sflib.get_all_picklist_values("Status")

assert values == ["Active"]

def test_raises_assertion_when_picklist_not_found(self, mock_robot_context):
self.sflib.selenium.set_focus_to_element.side_effect = ElementNotFound()

with pytest.raises(
AssertionError,
match="Picklist 'Status' was not found on the page.",
):
self.sflib.get_all_picklist_values("Status")

def test_uses_custom_timeout(self, mock_robot_context):
option = mock.Mock(text="Active")

with mock.patch.object(self.sflib, "scroll_element_into_view"):
self.sflib.selenium.get_webelements.return_value = [option]

self.sflib.get_all_picklist_values("Status", timeout="15s")

_, kwargs = self.sflib.selenium.wait_until_element_is_visible.call_args
assert kwargs["timeout"] == "15s"