Transcript from the "Types of Tests" Lesson
>> Mike North: Unit tests just like all tests are automatically generated by ember-cli in a very basic way. They test in isolation and that is important because a lot of the things that we've talked about that are globally available like components I've said. If it's in the components folder, you can use it in any template, not true in the unit test.
[00:00:26] Unit test is you start with sort of an empty context only seated with the object that you are aiming to test and then anything else, there is a needs option when you're setting up the test module. Where you can bring in additional objects that are necessary. For example if you're unit testing a model and it relates to another model.
[00:00:50] There's like a has many relationship. You'll need to bring in that other model so that you can kind of have a complete meaningful scenario, and this will also make it clear how coupled together things start to get. Because if you have a unit test and you're needing you know 15 other things you're not really writing a unit test any more.
[00:01:14] And it may be time to reconsider shifting towards something else. These run really, really quickly and that's why when you find unit testable chunks of code go for this. Get a lot of confidence where it makes sense from unit tests and leave the acceptance tests and everything else for the things that are more difficult like routes.
[00:01:38] So component integration tests. The important thing to realize here is what you are using to set up a scenario. And I can actually show you what one looks like what are the other generated test cases. GithubOrg test. And this was a major major improvement. It used to be very difficult to set up, like some you know handle bars snip it and to build a test case around that now, you're actually just render in line.
[00:02:17] As long as you put hbs before it, it'll get treated as a handlebars template and not just as a string and you render something and then, you can test it. And you can get and set and that's the equivalent of getting and setting on the component itself. So, you can really.
[00:03:07] You just do this.on myAction so if we were, for example, and this is a preview of what we're gonna work on in a second. We have an action that comes out of our component whenever favoriting is tiled. And this will let us validate that. In fact, when you click it, the action is fired.
[00:03:26] But this is a very easy way of doing that and It's come a tremendously long way compared to the hoops you used to have to jump through. So finally, Acceptance Tests, you're testing the app as a whole. It's slower. It will attempt to make API requests, because it's just programmatically driving your app.
[00:03:47] So, if you are not Interested in actually making API requests potentially, if you have an app that changes data and you're gonna end up creating a bunch of test records and polluting your API. And polluting your data base basically you may want to use something like Pretender or Ember CLI Mirage, both of which are used to mock API.
[00:04:14] And in addition to that, you cannot use those. But, just be aware that that is sort of a conceptually a different kind of testing, where you're you're really making sure the contract between the API and the URL are intact. You're really hitting an API getting real data. And in that case you're gonna write your test differently and you're probably not going to be deleting things and creating things quite so much.
[00:04:45] So in acceptance tests and this is where a lot of complexity exist because in theory, if you have a product owner and they say, your thing needs to be able to do this and this, and this, and this. You may be building an acceptance test to represent those product requirements.
[00:05:03] So these are the tests that get big and a little bit complicated. So a lot of helper functions to ease that pain, we've got some synchronous helpers that are really about reading the current situation reading state. As I said before when we're running tests, especially when we're running in the browser your app is running.
[00:05:28] It's just rendering the whole Ember app into a div. Be aware of this if you use the global jQuery selector. You may pick up parts of the test runner if you're not careful, so that's what this find synchronous helper is for. And make sure that you're looking up elements only within your ember application and you're not gonna grab the check boxes that turn on and off different test modules and things like that.
[00:05:56] Asynchronous test helpers are really interesting. So, these are for things that may trigger a transition or other sorts of asynchronous behavior. What's happening under the hood here is that each of these is essentially returning a promise and accumulating promises in an array behind the scene. And basically you're chaining promises together to run things asynchronously.
[00:06:25] So you can write synchronous looking code but really you can deal with asynchrony within the pieces of this code. So, if we look at this, visit, andThen, and click are all asynchronous test helpers. So, we start by visiting a URL, and we know that the router's gonna deal with the transition there, and potentially you're making a real API request.
[00:06:53] And we have this promise aware hooks. We have to wait until that resolves. So, this is going to add a promise to the array. When you define visit. Right? And then we're immediately going to proceed to the next step. And we're going to define the next step, and then we're going to define the next step, and we're going to define the next step.
[00:07:11] And so now we have this chain of promises, so this code will actually evaluate really quickly, because you're just sort of scheduling work. And then when visit is complete the callback to end then will be run and when that's complete the click will be run and when that's complete, you know you sort of just go down the line so that everything happens in the proper order.
[00:07:37] And you can actually write your own asynchronous test helpers. For example, Liquid Fire which is a popular way to animate transitions and other things in ember. The animations take time. They actually add time to the transitioning between two states in an application potentially. If your API call comes back right away but you still say I want a 0.5 second transition, you know that's a new time that has to be taken into account.
[00:08:08] And so it communicates with the testing tooling and says here's a new promise and wait until that's done before we say good to go, proceed to the next step. Everybody clear on this stuff? Now, one thing you have to be careful of, so as I mentioned, this is basically, this code here is like creating four promises in a row.
[00:08:35] If we had some synchronous code in between a couple of these things, we have to remember that that will be evaluated immediately, and so if we had like asynchronous click. If we just did dollar sign, dot selector dot click using the jQuery click function. That will be evaluated right away.
[00:08:56] So you don't want to mix a sync code with sync code. What you wanna do is use this andThen helper which gives you a place to put sent code in the correct spot so that it's part of this promise chain. But everything at the top level of an acceptance test should really be one of these async test helpers.
>> Mike North: So Mocking API Responses, pretender is sort of a lower level library. Though the way it works and it's by the way completely independent of ember, used heavily in ember but it is very generic. What it does essentially is it hijacks XML HTTP request and puts something else in its place to intercept attempted XHR.
[00:09:50] And you set up a mock server before your tests start running and you say these are the URLs that I expect request to be sent out to you and here is the way to handle those requests. And then when you start running it knows what to do and it will in fact raise errors if it sees traffic go out, if it sees attempts to make requests that are not on the list.
[00:10:18] You can define pass throughs which let you allow certain things to go through. But a very useful tool for mocking XHR. Mirage actually builds on top of Pretender and gives you just some additional sugar, the ability to have sort of an in memory database of records that you can return.
[00:10:38] And particularly if you're operating at a high level and you're just making standard JSON RESTful API requests. Mirage is probably a good option as well.