Search code examples
angularjsseleniumprotractorangularjs-e2ee2e-testing

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?


Solution

  • 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.