2

My workmate is working with Angular Material and he's using the mdToast this way: (in the else statements)

$scope.login = () => {
    $scope.loading = true;
    authService.login($scope.username, $scope.password, (result) => {
        if (result) {
            if (result === true) {
                $location.path('/');
            } else {
                $mdToast.show($mdToast.simple().textContent($filter('capitalize')($filter('translate')('passwordNotValid'))).position('top right').hideDelay(3000));
                $scope.loading = false;
                $("#input_username_login").focus();
            }
        } else {
            //error callback from server
            $mdToast.show($mdToast.simple().textContent($filter('capitalize')($filter('translate')('passwordNotValid'))).position('top right').hideDelay(3000));
            $scope.loading = false;
            $("#input_username_login").focus();
        }
    });
};

I need to test the text of the resulted toast but it seems like Angular Material's mdToast uses ng-if. My workmate hasn't any HTML code for the toast (he's just using the controller above to generate it) even so when the toast is triggered the next code appears for a few seconds in the DOM:

screenshot of the generated md-toast

I've tried, among other things, slowing down the toast's disappearance with browser.wait, waitForAngular and so on, but didn't work. I'm stuck with:

it("should show error toast in English when user fails login", function(){        
    login.email_address_field.sendKeys('random_user@correo.com');
    login.password_field.sendKeys('hardest_pass_123');
    login.login_button.click();
    expect(element(by.tagName('md-toast')).element(by.tagName('span')).getText()).toBe('Incorrect username and/or password');
});

3 Answers3

2

I found a solution using this answer as an example. My spec is:

it("should show error toast in English when user fails login", function(){        
    login.email_address_field.sendKeys('random_user@correo.com');
    login.password_field.sendKeys('hardest_pass_123');
    login.login_button.click();
    browser.ignoreSynchronization = true; 
    browser.sleep(1000);
    expect(element(by.tagName('md-toast')).element(by.tagName('span')).getText()).toBe('Incorrect username and/or password');
    browser.ignoreSynchronization = false;
});
Community
  • 1
  • 1
1

You can use ExpectedConditions to make your script wait till the toaster message is displayed.Once the toaster is displayed then you can validate the message as well.

var EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(element(by.tagName('md-toast'))),5000);
expect(element(by.tagName('md-toast')).element(by.tagName('span')).getText()).toEqual('Incorrect username and/or password');
Sudharsan Selvaraj
  • 4,792
  • 3
  • 14
  • 22
  • Thanks but I tried it and doesn't work due to timeout, I also investigated about [here](https://github.com/angular/protractor/issues/169) and [here](https://github.com/angular/material/issues/2704) and it seems like is an issue that hasn't been resolved ( _I mean without workarounds and so on _ ¬¬ ) – Andrés Felipe Parra Arteaga Dec 16 '16 at 21:57
0

This spec worked for me and it does not use sleeps. The important thing to note here is that the browser.ignoreSynchronization flag must be set while the browser is waiting. Due to the asynchronous nature of the browser.wait, changing ignoreSynchronization must be done after the browser.wait promise resolves or else it could have no effect.

// a close button that appears on the md-toast template
const closeToastButton = $('[data-automation="toast-close"]')
const cond = protractor.ExpectedConditions
function waitToastShow() {
    return browser.wait(cond.elementToBeClickable(closeToastButton), 5000)
}
function waitToastHide() {
    return browser.wait(cond.invisibilityOf(closeToastButton), 5000)
}

screenshot = name => browser.takeScreenshot().then(/* save fn */)

describe('a suite ... ', () => {
    it('takes screenshots of an md-toast once shown and after hidden', function () {
        // ... actions that launch an md-toast using $mdToast.show({ ... })
        browser.ignoreSynchronization = true
        waitToastShow().then(() => {
            screenshot('toast-showing.png')
            waitToastHide().then(() => {
                screenshot('toast-hidden.png')
                browser.ignoreSynchronization = false;
            })
        })
    });
}
activedecay
  • 10,129
  • 5
  • 47
  • 71