How to test angular views accessible after a login? - angularjs

I am using protractor to test my angular app, where most of the views are accessible for authenticated users only.
Currently, I placed the login action in beforeEach:
beforeEach(function() {
browser.get(site + '/account/login');
element(by.id('Username')).sendKeys('testuser');
element(by.id('Password')).sendKeys('letmein');
element(by.css('[value="Log In"]')).click();
});
The problem is for every it('should....') test, the webdriver visits the login page and perform the same log in ritual over and over again.
I guess there must be a better way to do it. How can we set up correctly so that the webdriver login only once and then perform all the it('should....') tests?

This can be done via the onPrepare field of the protractor configuration file.
An example configuration file with login is provided in Protractor itself.
onPrepare: function() {
browser.driver.get(env.baseUrl + '/login.html');
browser.driver.findElement(by.id('username')).sendKeys('Jane');
browser.driver.findElement(by.id('password')).sendKeys('1234');
...
}
Alternatively, you can make use of the fact that Jasmine tests are ordered. Thus, instead of logging in before every test, you can have your first it login.
I typically organize my Jasmine tests into larger suites, with the first it signing in, and the last it signing off.
The obvious disadvantage is that your tests are not entirely independent, but in return test execution is substantially faster. You can even argue that doing multiple things after logging in is more realistic than logging on and off for every action.
Yet another solution is to use the Jasmine 2.x beforeAll and afterAll notations of (see this answer). This does require that you use the newest version of Protractor, as pre 1.5 versions of Protractor only worked with Jasmine 1.x.

Related

Protractor how to run login test script first

I am trying to test an Angular Single Page application with protractor. I need to run the login script first. Only then I can move to other routes since there is a check for token in localStorage on route change.
Is this testing approach correct?. In that case I need to run the login script first. Does protractor allows to control the spec file order.
Or should I run the each script independently by hardcoding the token in localStorage (Should I do login api call independently before each test).
My login script contains the following
it('Login with wrong email', function() {
})
it('Login with correct email', function() {
})
So after running the Login with correct mail I will get the accessToken which will get stored in localStorage and I can continue testing other routes. Is this the correct approach. If not how do I test a single application with login from end to end.
In protractor Style Guide it is mentioned as
Make your tests independent from each other
So should I use beforeAll, beforeEach to get the access token and store in localStorage before each test. In that case please explain me how to do it.
Any help is greatly appreciated.
Thanks.
As highlighted in the Protractor FAQs, you can specify your login code in the onPrepare section of your conf file. Here is an example.
You can also achieve this in beforeAll but that adds unnecessary overhead to your test scripts. Altering the localStorage is possible, but not in the spirit of e2e testing since a lot can go wrong wrt LS, and you will end up wondering if it is your app or your LS modification code that caused this.

Protractor browser.driver.getCurrentUrl vs browser.getCurrentUrl

I'm running an Angular app and I'm trying to get the current URL when testing on protractor. Which one to use?
browser.driver.getCurrentUrl() or browser.getCurrentUrl() ?
If this is an Angular application under test - use browser, otherwise - browser.driver.
To quote #jmr from a relevant github issue:
If you need to interact with a non-Angular page, you may access the wrapped webdriver instance directly with browser.driver.
Though, note that both are gonna work if this is Angular application under test. Some people even said that found browser.driver more reliable if it the sync time is longer than usual:
Just to add to this - I find that browser.driver works better on AngularJS apps that take time to sync. I have tried both and for some reason browser.driver is more reliable.
Though, I've personally used browser.getCurrentUrl() and cannot recall any problems.

Possible to get unique browser instances in e2e specs written for protractor?

I'm using protractor to run some end-2-end tests for an Angular application, and from what I can tell, all the specs I specify in my config file end up sharing the same instance of protractor's browser.
Normally this wouldn't be a problem, but I am also using http-backend-proxy to set up mock responses to my application's ajax calls. This module uses the browser instance, and it seems that setting up mock responses in one spec pollutes the browser instance for subsequent specs, causing all the specs to use the mock response strategy defined in the first spec.
Obviously this creates some problems for test isolation.
Has anyone dealt with something similar?
[edit]
I did not find a way to create multiple browser instances, but did find a way to deregister http-backend-proxy responses between tests, which accomplishes the test isolation I was looking for. For future reference to anyone that runs into this same problem, I was using:
proxy.onLoad.when()
setups to handle my mock responses. You can deregister these with:
proxy.onLoad.reset()
If you place these in beforeEach() and afterEach() blocks, respectively, you can accomplish isolation both between tests within a given spec, and between separate spec files.

AngularJS e2e tests hang when changing between two separate angular apps

I have a frustrating problem: I want to write end to end tests for a complex angular app. The problem is that the login screen is a separate app. The initial idea was that it would branch out to separate other angular apps in our ecosystem based on the login credentials. It works like a charm. For the tests it is a nightmare though.
The tests work as expected but as soon as correct credentials are entered and the main angular app is loaded the tests just time out. No error message or debug output whatsoever, its just waiting. I can see the page is loading correctly.
Now I thought I would skip this part and test right on the target app but thats not working either since I need to initialize the server with the right credentials first (= go through the login screen).
I tried this with the karma scenario runner and protractor, both show the exact same behavior. Can I tell them to reinitialize after the target page is loaded?
So when protractor times out, the error message shows a link to the faq. Right on top there's the explanation for this problem. Apparently the app sends continuous requests (maybe because I am using socket.io), so Angular is never finished.
This problem has nothing to do with the separate apps.
The issue link was very helpful. Since I am not willing to touch any of the pages code I settled with
browser.ignoreSynchronization = true;
and
browser.sleep( ... );
The tests now work as expected.

PhantomJS integration testing with angular against live backend

I am trying to make my e2e test environment to be like the actual production environment. I discovered that when I take out the ngMockE2E from my app and run tests that actually hit the backend server then all my tests in PhantomJS fail. In all other browsers tests always pass.
I'm not sure what the cause of this is. All I know is that when I put the ngMockE2E back in then all tests pass in PhantomJS and when I take it out the tests that depend on the xhttp request fail.
One more thing the live backend is cross origin. But like I said it works fine in all other browsers. I'm wondering if PhantomJS doesn't have cors support.
Does anyone know how to remedy this? Am I supposed to always use the mocks?
For E2E testing with a real back end, I would consider using Protractor. As far as I know, ngMock and ngMockE2E are both made to fake a connection to a real server. With these libraries you can unit test your Angular project so that it works isolated.
Note that it is a bit more work to setup E2E testing with Protractor if you start from scratch. There are however also starter projects (Yeoman), which already have this setup for you. You could use generator-angular-gulp for example for your application, or you could have a look how they have set things up.

Resources