Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

problems modeling complex controls #31

Open
SiKing opened this issue May 6, 2020 · 3 comments
Open

problems modeling complex controls #31

SiKing opened this issue May 6, 2020 · 3 comments

Comments

@SiKing
Copy link

SiKing commented May 6, 2020

I am having problems modelling slightly complex controls, and the documentation has only trivial buttons and links.

I have a situation like this:

  1. Our app has navigation tabs along the top of the page for different sections of the app. As an example, we can use stackoverflow.com and the tabs (buttons?) along the top: "Interesting", "Bountied", "Hot", "Week", "Month".
  2. I wanted to have one method, to which I can pass the name of the tab as a param. Something like NavigateTo.page(String), as in actor.attemptsTo(NavigateTo.page("Interesting")).

As a hint I was able to find this, but it is not clear where the find(...) static import comes from.

I constantly find myself struggling to model something in Screenplay, that I used to whip up without a second thought using PageObjects:

public class NavigateTo implements Task {

    private String pageLabel;

    public NavigateTo(String pageLabel) {
	this.pageLabel = pageLabel;
    }

    @Step("{0} navigates to page #pageLabel")
    @Override
    public <T extends Actor> void performAs(T actor) {
	// TODO: all this should be some kind of PageObject thing?
	List<WebElementFacade> labels = BrowseTheWeb.as(actor).findAll(By.className("s-btn"));
	for (WebElementFacade label : labels) {
	    if (label.getText().contains(pageLabel)) {
		actor.attemptsTo(Click.on(label));
		return;
	    }
	}
	throw new NavigationPageNotFound(pageLabel);
    }

    public static NavigateTo page(String pageLabel) {
	return Instrumented.instanceOf(NavigateTo.class).withProperties(pageLabel);
    }
}

Can you help?

@globalworming
Copy link
Collaborator

find is a method of the PageObject. extract() though I can't find anywhere, maybe the docs are outdated? find only makes sense when you do actions via page objects and you don't really want that. Best practice is to decouple actions from page objects. see https://johnfergusonsmart.com/beyond-page-objects-liberate-chains-ui-think/ and https://www.infoq.com/articles/Beyond-Page-Objects-Test-Automation-Serenity-Screenplay/

I would propose something like this:

... actor.attemptsTo(LookupQuestions.labeled("Hot")) ...

class LookupQuestions extends Performable { ...
    actor.attemptsTo(Open.browserOn(new QuestionsPage()))
    actor.attemptsTo(Click.on(QuestionsPage.displayByLabel("Hot"))) ...

@DefautlUrl("https://stackoverflow.com/")
class QuestionsPage extends PageObject {
  static Target displayByLabel(String s) {
    return Target.the("button labeled" + s).locatedBy("some css locator using " +s)

@wakaleo
Copy link
Member

wakaleo commented May 6, 2020

You could also wrap the CSS locators in enums and have an enum value for each tab.

@SiKing
Copy link
Author

SiKing commented May 7, 2020

I eventually came up with:

public class NavigateToSection implements Task {

    private String label;

    public NavigateToSection(String label) {
	this.label = label;
    }

    @Step("{0} navigates to section '#label'")
    @Override
    public <T extends Actor> void performAs(T actor) {
	actor.should(seeThat(the(Section.labeled(label)), isCurrentlyVisible()).orComplainWith(NavigationSectionNotFound.class, label));
	actor.attemptsTo(Click.on(Section.labeled(label)));
    }

    public static NavigateToSection labeled(String pageLabel) {
	return Instrumented.instanceOf(NavigateToSection.class).withProperties(pageLabel);
    }
}
public class Section {

    public static Target labeled(String label) {

	return Target.the("application section " + label).locatedBy("//a[contains(., '" + label + "')]");
    }
}

This seems to work for my use-case, for now. I seem to be struggling more with how to express what I want in English and where are all the bits and pieces. I refactor almost everything every day, as I build up more stuff. That whole Open-Closed Principle is completely not working for me. :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants