Currently, I am in the process of writing end-to-end tests for an application that is under development. I am specifically focusing on creating a test for alerts generated by the alert directive (Angular UI Bootstrap) within a wrapper directive. Below is the code snippet that outlines my progress:
Let's start with the wrapper directive responsible for generating alerts:
// Import our directive controller
// The controller includes the necessary alert functions for the Angular UI Bootstrap alerts directive
import InfoAlertController from './info-alert.controller.js';
let moduleName = 'infoAlert';
// ## Directive Definition
class InfoAlert {
constructor() {
this.template =
`
<div>
<alert
ng-repeat="alert in vm.alerts"
type="{{ alert.type }}"
close="vm.closeAlert($index)" >
{{ alert.msg }}
</alert>
</div>
`;
this.restrict = 'E';
this.scope = {};
this.bindToController = {
name : '@?'
};
this.transclude = true;
this.controller = InfoAlertController;
this.controllerAs = 'vm';
}
// ### Optional Link Function
link (scope, elem, attrs, vm, transclude) {
}
}
export default [moduleName, directiveFactory(InfoAlert)];
Next, we can see how the directive is implemented in the user login
component view:
<info-alert
name="loginAlerts">
</info-alert>
The user login
component acts as another directive and consists of a form with Angular validation that interacts with an Authentication service.
Now, let's take a look at the test scenario I am struggling to create:
describe('login component', () => {
it('should display an error after failed authentication', () => {
browser.get('/login');
element(by.model('vm.user.username')).sendKeys('nerfherder');
element(by.model('vm.user.password')).sendKeys('badpassword');
element(by.css('.btn-custom')).click();
let e = element(by.repeater('alert in vm.alerts').row(0));
// No matter what I try, this always fails
expect(e.isDisplayed()).toBe(true);
});
});
When running the test, I receive an error message indicating Expected 0 to be greater than 0
, suggesting that the method I am using to locate the alerts is not effective. I have attempted to target the alerts by their class using
element(by.css('.alert-danger'));
and element(by.css('.alert'));
without success. Even using browser.waitForAngular();
did not yield the expected results.
I also experimented with Protractor Expected Conditions implementation, but unfortunately, it did not resolve the issue either.
While manual testing proves that all functionalities are operational and alerts are triggered during execution, I am still unable to overcome this hurdle. Any assistance would be greatly appreciated, as I find myself stuck at this point.
Solution
A solution based on alecxe's answer is presented below:
describe('login component', () => {
it('should display an error after failed authentication', () => {
let EC = protractor.ExpectedConditions;
browser.get('/login');
element(by.model('vm.user.username')).sendKeys('nerfherder');
element(by.model('vm.user.password')).sendKeys('badpassword');
let alert = element(by.repeater('alert in vm.alerts').row(0));
let alertLoaded = EC.visibilityOf(alert);
element(by.css('.btn-custom')).click();
// Targeting UI Bootstrap alert class
let e = element(by.css('.alert-danger'));
browser.wait(alertLoaded, 5000);
expect(e.isDisplayed()).toBe(true);
});
});
Upon implementing this revised test approach, the test now executes successfully.