I'm starting to embrace and utilize the screenplay pattern with selenium testing. It's a new concept for me which has me un-learning old behavior. I've been slowly translating some sample tests using screenpy from an existing test suite.
One of the things I am struggling with is how to handle "traditional" PageObject style of checking isLoaded
. This would normally be a method that looks at several locators using specific search strategies (is_enabled, is_displayed, etc) to determine if that particular page object had indeed loaded.
Using the screenplay pattern I've got a separate module for each unique area which contains all the locators for it. For instance login_page, header_menu, dash_board_content, etc.
I then have action/task classes which which handle things like combining common selenium actions to allow a user to perform domain actions; e.g. LoginSuccessfully, MakeFeatureSelection, DeleteDataEntry.
I find myself wanting to gravitate to the same behavior in PageObjects by trying to figure out how to implement isLoaded vs waiting for PageObject to load. In the "traditional" PageObject style, I would combine the target and the search strategy and then just call either the Wait or the find methods.
In screenplay I can call the two different Wait or Find action classes on the Targets, but since they are missing the search strategies I've ended up with duplicating the set of Targets. It feels wrong to have the set of targets in two different places. I can't tell if this is because I'm so used to using page objects.
# under the hood this is doing a driver.find_by(locator).is_enabled()
class CheckIfLoginPageIsLoaded:
@beat("{} attempts to CheckIfLoginPageIsLoaded")
def perform_as(self, actor: "Actor"):
actor.should_see(
(Element(login_page.PASSWORD), IsClickable()),
(Element(login_page.USERNAME), IsClickable()),
(Element(login_page.FORGOTPASS), IsClickable()),
)
#under the hood this is doing a WebDriverWait().until(EC.element_to_be_clickable(locator))
class WaitForLoginPage:
def perform_as(self, actor: "Actor"):
actor.attempts_to(
Wait.for_the(login_page.PASSWORD).to_be_clickable(),
Wait.for_the(login_page.USERNAME).to_be_clickable(),
Wait.for_the(login_page.FORGOTPASS).to_be_clickable(),
)
I need a guru to smack my hand and say "No.. bad kitty" but I feel blinded by old habits. Am I over thinking this or is there a solution in screenplay pattern that I'm not seeing?