e2e protractor test requiring oauth authentication e2e protractor test requiring oauth authentication angularjs angularjs

e2e protractor test requiring oauth authentication


The key is to use browser.driver.get instead of browser.get, and to use browser.driver.sleep(someMilliseconds) to let angular load at your final destination before using the angular-specific commands.

Here's my working protractor spec that first authorizes to Google and then counts the items in a repeater:

it('allows the user to add new slides', function () {    browser.driver.get('http://localhost:3000/editor/?state=%7B"action":"create"%7D');    // at this point my server redirects to google's auth page, so let's log in    var emailInput = browser.driver.findElement(by.id('Email'));    emailInput.sendKeys('user@googleappsdomain.com');    var passwordInput = browser.driver.findElement(by.id('Passwd'));    passwordInput.sendKeys('pa$sWo2d');  //you should not commit this to VCS    var signInButton = browser.driver.findElement(by.id('signIn'));    signInButton.click();    // we're about to authorize some permissions, but the button isn't enabled for a second    browser.driver.sleep(1500);    var submitApproveAccess = browser.driver.findElement(by.id('submit_approve_access'));    submitApproveAccess.click();    // this nap is necessary to let angular load.    browser.driver.sleep(10000);    // at this point the protractor functions have something to hook into and     // will work as normal!    element(by.id('new-slide-dropdown-trigger')).click();    element(by.id('new-text-slide-trigger')).click();    var slideList = element.all(by.repeater('slide in deck.getSlides()'));    slideList.then(function(slideElements) {        expect(slideElements.length).toEqual(1);    });});


I have a Google Auth page object (below) that does the whole job for me.

The key here is "isAngularSite(false);" function witch instructs webdriver if we are entering 'angular' or 'non angular' website. (implementation below).

/* global element, browser, by */'use strict';var GOOGLE_USERNAME = 'my.account@google.com';var GOOGLE_PASSWORD = 'password';var ec = protractor.ExpectedConditions;var Google = function () {  this.emailInput = element(by.id('Email'));  this.passwordInput = element(by.id('Passwd'));  this.nextButton = element(by.id('next'));  this.signInButton = element(by.id('signIn'));  this.approveAccess = element(by.id('submit_approve_access'));  this.loginToGoogle = function () {    var self = this;    /* Entering non angular site, it instructs webdriver to switch        to synchronous mode. At this point I assume we are on google       login page */     isAngularSite(false);     this.emailInput.sendKeys(GOOGLE_USERNAME);    this.nextButton.click();    this.passwordInput.isPresent().then(function () {      browser.wait(ec.visibilityOf(self.passwordInput), BROWSER_WAIT).then(function () {        self.passwordInput.sendKeys(GOOGLE_PASSWORD);        self.signInButton.click();        browser.wait(ec.elementToBeClickable(self.approveAccess), BROWSER_WAIT).then(function () {          self.approveAccess.click();          /* Now we are being redirected to our app, switch back to             async mode (page with angular) */          isAngularSite(true);        });      });    });  }}module.exports = new Google();

--- throw this into protractor.conf.js

onPrepare: function () {    global.isAngularSite = function (flag) {      console.log('Switching to ' + (flag ? 'Asynchronous' : 'Synchronous') + ' mode.')      browser.ignoreSynchronization = !flag;    },    global.BROWSER_WAIT = 5000;  }

--- that's how you would use it:

it('should login though google', function(done) {    mainPage.loginBtn.click().    then(function () {      loginPage.connectWithGoogleBtn.click();      googlePage.loginToGoogle();      browser.wait(mainPage.userName.isPresent()).      then(function () {        expect(mainPage.userName.getText()).        toEqual('my.account@google.com');        done();      });    });  });


You should use waitForAngularEnabled to enable/disable waiting for Angular tasks with protractor. By default it will be enabled. You can use the following:

// do things on your Angular application// go to external oauth pagewaitForAngularEnabled(false)// login on oauth page and redirect to your Angular applicationwaitForAngularEnabled(true)browser.get('/home') // this is a page from your Angular application

waitForAngularEnabled returns a promise. The browser.get function blocks until the Angular page is loaded.