Markus Johansson
Markus Johansson

Reputation: 3773

Click visible button in protractor?

I have a page which looks something like this. It's a wizard with steps. Depending on the "step" scope variable, a different part of the wizard is shown:

<div ng-show="step == 'first'">
  <button>Next</button>
</div>

<div ng-show="step == 'second'">
  <button>Next</button>
</div>

<div ng-show="step == 'third'">
  <button>Next</button>
</div>

To click the next button I run into problems though. Because there are three of them. The following code returns all of them:

var next = element(by.buttonText('Next'));

And doing:

next.click();

will click the first one. How can I find the visible button only, and click that one?

Upvotes: 2

Views: 1627

Answers (3)

BarretV
BarretV

Reputation: 1197

You should be able to chain the elements to specify which next button you want to click.

var firstNext = element(by.css('div[ng-show="step == \'first\'"]')).element(by.buttonText('Next'));

var secondNext = element(by.css('div[ng-show="step == \'second\'"]')).element(by.buttonText('Next'));

var thirdNext = element(by.css('div[ng-show="step == \'third\'"]')).element(by.buttonText('Next'));

// We are on the first step
firstNext.click();

// We are on the second step
secondNext.click();

// We are on the third step
thirdNext.click();

Upvotes: 0

alecxe
alecxe

Reputation: 473803

Here is a bit more cleaner version in terms of understanding that uses filter() to filter a single visible button and click it:

function clickButton(text) {
    var buttons = element.all(by.buttonText(text));
    var visibleButton = buttons.filter(function(button) {
        return button.isDisplayed().then(function(isVisible) {
            return isVisible;
        });
    }).first();
    visibleButton.click();
}

As a bonus, you'll also get an error if there are no visible buttons found, as opposed to your current approach which would not fail in this case.

Upvotes: 1

Markus Johansson
Markus Johansson

Reputation: 3773

First I was confused by isDisplayed returning a promise. This function is what I came up with:

function clickButton(text) {
    var buttons = element.all(by.buttonText(text));
    buttons.each(function(button) {
        button.isDisplayed().then(function(isVisible) {
            if (isVisible) {
                button.click();
            }
        })
    });
}

Which can be used like this:

clickButton('next');

Upvotes: 1

Related Questions