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

Better ways to override implicit timeouts for Screenplay Targets? #558

Closed
nbarrett opened this issue Oct 3, 2016 · 3 comments
Closed

Better ways to override implicit timeouts for Screenplay Targets? #558

nbarrett opened this issue Oct 3, 2016 · 3 comments
Labels

Comments

@nbarrett
Copy link
Contributor

nbarrett commented Oct 3, 2016

There are times when I want to immediately work out whether a screenplay target is visible or not, but not wait until my implicit timeouts have completed. Historically (pre-Serenity) I did this most effectively by doing a findAll() with a 0 second wait condition. So to emulate this in Screenplay/Serenity, I've created a helper method as follows:

public class ResolveImmediately {

    static final Logger LOGGER = LoggerFactory.getLogger(ResolveImmediately.class);

    public static WebElementFacade element(Target target, Actor actor) {
        ProcessTimer processTimer = ProcessTimer.start();
        BrowseTheWeb.as(actor).setImplicitTimeout(0, SECONDS);
        WebElementFacade element = target.resolveFor(actor);
        BrowseTheWeb.as(actor).resetImplicitTimeout();
        LOGGER.debug(target + " resolved in " + processTimer.executionTime());
        return element;
    }

    public static boolean isEnabled(Target target, Actor actor) {
        String disabled = element(target, actor).getAttribute("disabled");
        return disabled == null || disabled.isEmpty();
    }

    public static boolean isDisplayed(Target target, Actor actor) {
        return all(target, actor).size() > 0;
    }

    public static List<WebElementFacade> all(Target target, Actor actor) {
        ProcessTimer processTimer = ProcessTimer.start();
        BrowseTheWeb browseTheWeb = BrowseTheWeb.as(actor);
        browseTheWeb.setImplicitTimeout(0, SECONDS);
        List<WebElementFacade> elements = target.resolveAllFor(actor);
        browseTheWeb.resetImplicitTimeout();
        LOGGER.debug(target + (elements.size() == 0 ? " not" : "") + " found in " + processTimer.executionTime());
        return elements;
    }

}

This seems like a hack. Is there a better way please?

@wakaleo
Copy link
Member

wakaleo commented Oct 3, 2016

You can use the WebElementStateMatchers.isCurrentlyVisible() matcher, e.g.

        then(dana).should(seeThat(the(ProfilePage.NAME), isCurrentlyVisible()));

@nbarrett
Copy link
Contributor Author

nbarrett commented Oct 4, 2016

Hmm, I don't actually want to use it in an assertion, but more to make a task conditionational e.g. how would I re-implement navigationRequired in the example below?

    @Step("{0} searches for the #workflowType")
    public <T extends Actor> void performAs(T actor) {
        if (navigationRequired(actor)) {
            actor.attemptsTo(
                    NavigateTo.theWorkflowOverviewPortal(),
                    Enter.theValue(Work.as(actor).workflowInformation().name())
                            .into(WorkflowTargets.WORKFLOW_OVERVIEW_SEARCH_FIELD)
                            .thenHit(ENTER),
                    WaitFor.targetToBecomeVisible(SearchResultsPage.container)
            );
        }
    }

    private boolean navigationRequired(Actor actor) {
        return ResolveImmediately.isDisplayed(actor, SearchResultsPage.container);
    }

@nbarrett
Copy link
Contributor Author

nbarrett commented Oct 13, 2016

Also, I want to immediately determine the count of items in a question where sometimes the number may be 0:

    private static int searchResultCount(Actor actor) {
        int size = Target.the("row Count").inIFrame(iFrame).locatedBy("#searchResultsDataGrid .dojoxGridMasterView .dojoxGridRowTable tr")
                .resolveAllFor(actor)
                .size();
        LOGGER.debug("searchResultCount:" + size);
        return size;
    }

But when the locator is not present a delay is incurred equal to webdriver.timeouts.implicitlywait, which in my project is 1 min. Is there a better way?

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

No branches or pull requests

2 participants