dman dman - 13 days ago 10
AngularJS Question

Protractor isSelected giving false reading after re-enabling checkboxes

I have a list of checkboxes and at the top a

all
checkbox. When toggling the all checkbox, all checkboxes will get deselected or selected.

By default/initially,
all
checkbox is enabled with all checkboxes checked. So, I will deselect the all checkbox and all the checkboxes will uncheck. This passes no with no issues in protractor:

it('all checkbox is deselected', function() {
modelsAllCheckbox.click();
expect(modelsAllCheckbox.isSelected()).to.eventually.be.false;
});

it('all models should be deselected', function() {
ppvPercentages.modelChoices().then(function(modelChoices) {
modelChoices.forEach(function(modelChoice) {
expect(modelChoice.isSelected()).to.eventually.be.false;
});
});
});

this.modelChoices = function(rowNumber) {
return element.all(by.repeater('model in vehicleCheckboxes.models'));
}


Then I re-enable the
all
checkbox. I visually can see, in the browser, the all checkbox being checked in all the checkboxes successfully being checked/selected. Hoewever, in the test to assert they are all selected fails:

it('all button is re-enabled', function() {
modelsAllCheckbox.click();
expect(modelsAllCheckbox.isSelected()).to.eventually.be.true;
// give time for all models to set
browser.sleep(3000)
});

it('all models are selected', function() {
ppvPercentages.modelChoices().then(function(modelChoices) {
modelChoices.forEach(function(modelChoice) {
expect(modelChoice.isSelected()).to.eventually.be.true;
});
});
})





<div class="overflow-container">

<!-- all checkbox -->
<input type="checkbox"
ng-model="vehicleAllCheckbox.models"
ng-change="toggleAllModels(vehicleAllCheckbox, vehicleCheckboxes.models, vehicleCheckboxes.year)">All

<div ng-repeat="model in vehicleCheckboxes.models | orderBy: 'description' track by model.description">
<!-- the rest of the checkboxes -->
<input type="checkbox"
ng-change="modelCheckboxToggle()"
ng-model="model.checked" >
{{model.description}}
</div>
</div>


I see all the checkboxes are checked in the browser viusally. Why is
modelChoice.isSelected()
giving false instead of true up re-enabling the all checkbox?

Answer

The problem is in the way you are locating the checkboxes. Currently, you are targeting the parent div elements since you are using the by.repeater() locator:

<div ng-repeat="model in vehicleCheckboxes.models | orderBy: 'description' track by model.description">

Instead, point modelChoices to input elements (your checkboxes):

this.modelChoices = function(rowNumber) {
  return element.all(by.repeater('model in vehicleCheckboxes.models')).all(by.model('model.checked'));
}

As a side note, I think you can improve the way you are expecting the checkboxes to be selected, by either using .each():

ppvPercentages.modelChoices().each(function (modelChoice) {
    expect(modelChoice.isSelected()).to.eventually.be.true;
});

Or, by using .reduce():

var allSelected = ppvPercentages.modelChoices().reduce(function (acc, modelChoice) {
    return modelChoice.isSelected().then(function (isSelected) {
        return acc && isSelected;
    });
}, true);
expect(allSelected).to.eventually.be.true;

Or, there are other ways as well.