Asserting $http request payloads without mocking them - angularjs

I'm writing Protractor tests to verify the successful creation of reports in our application. A report is created via a series of complex UI interactions within a dialog and saved via an AJAX POST request to a REST API.
I've written tests for the complex UI interactions within the modal, but I'm at a loss for how to test the POST request within the same Protractor tests. Ideally, I'd like to be able to make assertions against the payload of the POST request to verify that the UI is sending the correct data to the API.
It's important to note that I do not want to mock the HTTP call--I need it to go through, since subsequent protractor tests navigate to the report and perform additional checks. My first thought was to somehow hook into the $httpBackend.passThrough() method, but I haven't had any success with that.
Any ideas how to accomplish this?

since subsequent protractor tests navigate to the report and perform additional checks
If you check that the report contains data to that matches which was submitted, you are, albeit indirectly, testing that the POST went through successfully. There is a reasonable argument that this is enough for the E2E test: it tests that the application behaves as he user would want. The user doesn't care how it's achieved: POST, websockets, carrier pigeon ;-)
Keep in mind that the usual aim of such tests is for them to fail if something is broken. If the POST isn't done correctly, then the subsequent tests that verify the displayed report would fail.
The downside is that you would have a bit less information about what has gone wrong than if you managed to test the POST as well. However, unit tests can help. If you have a failing unit test that localises the issue, you write a fix that makes it pass. If you don't have a failing unit test, you can investigate the issue by debugging, add a failing test that highlights the issue, and fix the code so it passes.

Related

How (or should) I test 3rd party module results in angular with jasmine?

I am just starting to get into unit tests but I seem to end up thinking in circles and would really like some guidance. I totally understand typical examples like how to test an adding function but my application isn't as simple.
An overview of my application (I can provide code if it will help):
I have services which basically make XHR calls to my API. Each service I have so far tested it goes to the right URL, mocked responses for success and error responses and I feel pretty happy it is tested enough.
Now my controller basically calls the service, grabs the data and on success calls angular-nvd3 nv.addGraph() with some config options to draw a chart. On error it shows a toast message.
So now I am wondering what exactly do I test in this controller? This is what seems right to me but some seem impossible to test:
service is called
the div has a chart in it on success (is this testable?)
a toast is displayed on failure (is this testable?)
I can check if the functions are called but the results don't seem testable to me. I can mock a response from the service call but that seems redundant to my testing on the service.
Any suggestions would really help, functions that manipulate data seem easily understandable to test but when it involves view elements or XHR requests I start getting confused as the expected success will always be accurate since it is mocked.
Thanks a bunch.
On your controller you could test:
Service is called (I think you're doing that already, good job)
You probably put the data from the Service into some variable, you could check if the variable was assigned properly
Toast.show was called with the message you want to be displayed in case of failure
It seems to me that testing if the div has a chart would be a candidate for an Automated UI test.

Unit testing - ignoring module run block

Is there a way to prevent an application run block from executing during unit tests?
My situation is that I have added some session checking logic to the run block, which redirects to a login page should session checks fail.
Now that I have added this run block in, all my other tests fail since they expect the login page to have been requested as I'm not ensuring the session check returns true before each test.
So is there a way to skip the run block for a unit test, or would it be something like mocking out the module in my tests so it doesn't have the run block included?
I'm probably thinking about this the wrong way, so please enlighten me!
Thanks
No, run block is part of angular app lifecycle.
I would suggest not to have this logic in .run, but transfer all authentication logic into some service. After that its easy to mock it.
If you can be more specific about app architecture, I can suggest more improvements.

Angular Unit/E2E testing with protractor and jasmine

I am writing an angular application, whereby my controller calls an API, that returns live data which I then display on my html doc.
I am using Protractor for my end to end tests, and jasmine for unit testing.
I am mocking my API call, to ensure the API is not called.
My question is whether I should be testing the API call with protractor, and check whether my html doc is updated following the GET request, or whether I should test the API call when conducting my unit tests with jasmine.
I have a feeling that the answer is that I should be testing this API call with both my unit and end to end tests, but am hoping someone on SO can provide clarity.
The main goal of unit testing is to test that your code (be it JavaScrip or otherwise) is doing what it should. Each test should be done against data that static or contrived and should never be run against an API. Static data gives you the control you need. If your code needs to branch when X equals 7, you can purposely set that value and verify that your code does indeed branch. When you run against an API you do not have that control. Even if you are the one that controls the API, doing unit testing against it is a bad habit to get into.
End to end testing is completely different. Here we are not testing that the code works on a granular level (we already did that in our unit tests) we are testing that the application works as a whole. When a specific button is clicked in the application, did the expected things happen? Do all of the expected elements appear on the page? You still need to be testing against known data, and doing that is just as crucial as in unit testing, but here you get to see how your app reacts against when running. Did a particular screen take too long to load? Did a button click not give you what you expected? This kind of testing lets you click through your application as a user would (except much faster.)
You should run both kinds of tests on your app. Unit tests should be run during the build process, and end to end tests should be run once the build completes.

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.

With Protractor 1.0.0 rc2 + is the browser.waitForAngular() still required?

I was watching a youtube video and in that there was an example:
loginPage.userName.sendKeys ...
loginPage.password.sendKeys ...
loginPage.loginButton.click();
browser.waitForAngular();
expect( ...
I thought Protractor was coded in such a way that it would do the wait without the need for a browser.waitForAngular().
Can someone confirm if I need the waitForAngular() in this example?
I think that whether you need browser.waitForAngular() depends on the application you're testing.
Not 100% sure on what the conditions are, but I have found that I required this method when my test is performing a task that requires a response from a server, such as changing a user's password in a web app.
On another note, in my experience, browser.waitForAngular() is not robust enough to handle every type of wait condition I've needed to perform.
For example, I'm writing tests for a web application where the user logs in through a non-Angular page and is directed to an Angular page. If I want to make assertions to test the elements present on the login landing page, I can't use browser.waitForAngular() because non-angular pages do not have access to this method. I've found that a more reliable way to tell the driver "wait for the page to fully load, then check the text present on the page" is to use browser.wait to explicitly wait for the presence or visibility of an element on the next page that you know will take the longest to load.

Resources