Angular transition to 2.0, part 7

BrieBug Solutions has created an online video series that provides information, tips, and insight on the transition from Angular 1.x to Angular 2.0. This video is a great resource for those in the industry who are interested in programming, typically programmers, to be aware of the Angular changes, as well as receptive to technology growth.

This video is seventh in our series on how to transition from Angular 1.x controllers/views to Angular 2.0. This video covers fixing the existing tests and writing new tests for our component based directive. We hope these step by step videos are easy to follow for those that are interested in the transition to the new and updated Angular software.

Welcome back to transitioning angular 2.0. This is the last video in the component refactor series before we get into type script and the final step of actually converting our code to angular 2.0 and this step is all about tests. So one thing you may have noticed when we were doing this all these changes is that we weren’t actually keeping all of our changes up to date. That’s a pretty bad practice. It’s not something that we would want to do. So however to keep each video simple and autonomous.

We wanted to just focus on the actual task at hand so now we are going to go in and fix what we already have so the first thing we want to do here is find our point a. let’s figure out where our tests are at and figure out what is going on. So I’m going to run gulp auto test. Now what this does is this goes in every time I make a change is this reruns the test and gives me feedback. We are going to go ahead and run this here. I already know we have some failures so don’t be too alarmed here. So we get 5 failures I’m going to scroll up to the top here. So let’s see here, it says that the first error is the app feature, admin, admin html was expected to equal app admin. Oh so remember back in one of the first videos there we refactored our code and we moved our admin pages. And admin and dashboard, outside of the app folder and put them into the feature folder.

Fortunately it looks like we still have some stuff that is pointing directly to the old. Here in the route spec it looks like my fending line so I’m going to come over here to features, admin route spec and let’s see here. Oh yep sure enough, we didn’t put that there. So let’s grab this. We are probably going to need this in a couple other spots. I bet if we look in dashboard route spec. yep same thing here. And let’s see here. Let’s see what happens when I save that. One more failure is gone. Ok so we have a message count provider.

We will come back to that. We have an unexpected call to api people. And we got one here getting app dashboard html. Since these are all related we want to go after these. This is a sidebar controller spec so let’s go find that. That is located in app layout. Sidebar controller spec. so here we just need to go ahead and put those in and save it. Now we still have 4 errors. Alright. It appears that we have one other place that this is causing a problem. I believe this is actually in our test helper. If we go look in our mock data. Here is the other one. So if we go ahead and paste this in correctly then save it. Now we are down to two failures. Great! This resolves all the template issues that we were seeing. Now we are down to a message count provider. And we have got an error for making an unexpected call to get an apipeople.

Alright so let’s go look at the dashboard controller spec. it looks like line 13 and dashboard controller spec line 13 alright. So what happens here is were actually creating using $controller. It’s actually creating an instance of the controller for us. So if we go look at the controller itself it is getting injected with message count, people and news. Where are those coming from? Well you may remember in our route here we have resolves. So here is message count people and news. So when these resolve they are actually added to the angular name space so that they are injectable into our dashboard controller.

Unfortunately that is not happening so we need to handle that. So what we are going to do is we are going to create a mock resolve. So come down here in our test helpers and we are going to create a new java script file and call it resolve mocks.js and let’s see here. We’re going to do our standard ify. Great! And inside of here we are going to have our use strict. Great! And then we are going to create a couple of modules and actually let’s see here.

We are going to do angular.module resolve. Just do a singular module. Great, so now we have our module. And now let’s go ahead and create a few constants. .constants. People and now we are going to use our existing mock data which should be on the window. So it will get loaded into global mock data. So that’s going to point to this file here .getmockpeople. So whenever we ask for people then it is going to go use mock data get people data to return that. Constant again. And message count. Great! We are going to hard code this for the value. And .constant the last one is news. And let’s see here.

Title is news title and description let’s make that news description. We don’t need anything too descriptive here we just need something so that we can then verify that yes it is working and what not great. Now we have our resolve mocks. And now all we need to do is wire these in so that they’re pointing correctly into the project. Great so what does that look like? Great! So now we are going to go back to our dashboard controller spec. so in here is where we are going to make our changes. So notice here hard app module. Dashboard. What this does is this tells our tests what modules to pull in. so in this case right now the only thing we are pulling in is app.dashboard. What we want to do though is bring in app.resolve. Let’s go look here.

Resolve mocks ya know let’s call it resolves. Great it is app resolves. Excellent. So now that should work. Let’s run that. Well we still have failures so this looks like a different issue now. So that went away but now the problem is we have an unexpected API people call.so instead of. When we are testing this instead of it actually mocking now this call is actually making this call directly back to our backend service and since we have this bard now outstanding requests well this says well hey anything that comes through that we are not expecting we haven’t told it about it should fail.

So the issue here is if you see we have stuff here to mock this out except for now when we go look for the controller it is not actually doing the load in here anymore. So it doesn’t really need to be here where it needs to be is over on the route because the route is the one doing the calls to the people, get message count and returning this news piece. So over in the route spec is where we need to move these. So let’s first remove this guy and put him over here right there. And then were going to go ahead and move our sign on stub and place this guy over here as well.

So now we go ahead and save it. But now we have 3 failures. So we didn’t solve our problem. And that may be let’s see here. Let’s move him up here and see what that does. Nope still the same 3 failures. That one is a different issue. Oh not able to find. Oh that’s why. So here we’ve got. We will go ahead and move him back to where he was. The problem here is data service, we haven’t told them where data service is coming from. So if you notice back over here on our dashboard controller spec. we injected data service and that then got added to global main space. So we need to remove it from here and bring it over here and add it right there. This is starting to get a little long so I typically like to have these each on their own line starting with dollar sign first and then anything what we have written last.

So now we are down to 2 failures. We are not able to find dollar sign in cue. Notice here that dollar sign cue being used we didn’t actually inject it so that one is over here as well with dollar sign cue. Great. Let’s do it the other way. Pull it from here to here. The cue is nice and short so I like it to be on top there. Hey we are down to one failure. Fantastic. So what is this one failure? This failure here is for the dashboard controller spec on line 28 and it’s saying that, oh that’s the wrong one. Come over here. Much better.

Line 28 for the dashboard controller spec. and it expects that something be logged and it should say activated. So if we go look at the controller itself. It should be saying activated this however the issue is that this needs init needs to be called however init is not available. It’s not exposed, there is no way to call it from over here so we have one to two choices, either we need to remove this or we need to make it is so that we can call the init function. So let’s go ahead and do the ladder.

So we are going to come over here and we are going to add init to the viewmodel. Init=init. Great. So now still fails because we are not actually calling init. So let’s go ahead over here and just do controller.init. Look there we go. We are successful. 39 of 39. Everything ran. Excellent. So this is a great starting point however this is not where we want to finish because. Let’s go ahead and close all of these. And let’s go up here to components and let’s go look at our people directive spec. its empty. So that’s no good. So we don’t have any tests for people directive.

The only thing I can do is I can come over here under the report coverage folder. I can expand this and then web storm here. I can right click on index and I can say open in browser default. So it will open it up in chrome and then I can see what is going on. So I can see here that my people component somehow is getting some tests run against it. I think it is because it is being created somewhere else. Actually it is just because most of this code is being executed because it is part of the directive itself. The people controller itself has nothing that is being executed. So that’s why we are showing partial coverage there. So let’s go ahead and just minimize that for now and we will come back to it. So now what we want to do is create our ify.

Part our use strict in here and let’s go ahead and start these tests. So the first thing we want to do is start with the describe. This helps form our structure for our tests. In our describe we are going to call it directive people. Put the case in and then give that the function frame. And all of our tests are going to be inside of this directive. And inside of here then I know we are going to need an element and I know we are going to need a view model and we are going to need a couple before eaches and we will talk about these. Let’s see here. In this case here we want to require modules and inject dependencies. Great and next before each we want this one to be create our directive. And the last thing we want to do here is before we get going too far is verify no outstanding repeat requests. Make sure that all tests are all external calls are mocked.

Why do we do this? Well we want to make sure that any sort of external calls that we are making are going now and are actually hitting a resource. These are unit tests not integration tests. And so any time we are making calls to the outside we want to mock those so we can control the inputs and outputs and make sure we can sufficiently test our services. So in this case here we are going to go ahead and pull in our modules. Let’s start with that so bard. If you don’t know what bard is go check it out.

You can search for bard js. It’s an excellent module written by ward bell who developed this for angular developers to make it simpler for running tests. So in our case here we are going to pull in app components and let’s see here. Let’s go look at what is being pulled in by our directive. So we don’t have any injections coming in. so that is good. So let’s start with app components. Everything we need should be contained in that. The next thing. I don’t want the whole deal. We want app component people. Just the component we want to pull in not anything else. The next thing we want to do is bard inject. Now this is going to pull in libraries that we need so that we are able to create our directive as well as any dependencies for the directive.

The directive itself doesn’t have any dependencies so we do not have to worry about that. So I know we need $compile I know we need $root scope. I know that we need $template cache. Great. So now sometimes depending on what we are using we might need $stake we might need $cue if we had any sort of mocks for any data services. In our case we are pretty simple so we won’t need any of that. Alright so for right now that should be good. We have required in our modules we have injected any dependencies. So we can now create our directive. So now that next step here is we need to go ahead and create our directive. The first thing that we need is html so we are just going to create a local variable in here for right now. And it will be angular.elements and lets add in here people/people. Great. So pretty simple we don’t need a whole lot there.

Next thing we need to do is get new instance of scope. So we want to say $root scope=$ root scope.$.new. This ensures that we get a brand new scope variable that doesn’t have anything attached to it. We don’t have to worry about any pollution. Great. The next one we need to do is tell template cache then we would request the template. We are already good to go we don’t need anything else from template cache. So were just going to use this blank string. So then we just need to tell it ok so components/component/people/people.html and it returns this. So basically what happens is when we create the directive it’s going to say hey template URL let me go load that for you. So one of the things that happens before that happens is it checks the template cache and it says hey do we already have this template local and if we do go ahead and give it to me. So we are faking template cache here to make it think we have everything that it needs so why would we want to give it nothing?

Wouldn’t we want to give it the real html? Well in our case we are doing unit tests, we are not doing ui integration tests and we are not doing any end tests. We are just doing functions. Those functions will be here. Functions such as persons. Okay great.so in this case here it makes it very simple, by us doing this we don’t have to worry about the template, there is no html or ui to worry about. Alright so the next step is we need to set our element variable=compile html. So this takes and compiles our html from up here and compiles it. This starts creating the actual directive and then it is injecting it into that scope for that integration. So fantastic. This is now starting to create our directive. So the next thing we need to do is wait for the directive to be created. So to do this we are going to use the scope again and we are going to say $digest element so this tells angular slow down let us go and process this.

Or actually it is a test basically calling and saying To go ahead and process what it needs to because the sync to call happening and then the end here we can get an instance of our controller by the element.controller and give it the name of the directive. So let’s rescue this here. Get the viewmodel. So if we go back to our directive here, notice it has this controller syntax here. This just points to a function. So nice and simple. Since this is a controller or a function, not an angular controller. Then all we do is ask it where the controller is based for the element. We also give it the name. The name comes from the directive. Just go ahead and copy the name people from here to here and that gets us our view model. Great outstanding.

This should go ahead and create our directive for us. Understand these are going to be called every single time before we actually run our tests. So the next thing we are going to do is do our first very simple tests. And we just want to say it successfully creates the directive. Great! So what we want to do is we want to check and make sure both our view model and controller, wait element and view model have value. So we want to expect the element to be defined. Great so we want to copy this and the other one I want here is the viewmodel is defined. Great. Uh oh so object/object is not a function. Oh got you.

In my haste I forgot it’s not just template cache when assigning something to it. Template cache is not a function it is an object and it has a function of put. Save this again. We successfully created that. Now if we come back over here. We pull up here. We refresh it. Now we have code coverage for part of the controller here. We assigned this here. This signing gets us partial coverage for this although we have never called that. So we are looking pretty good. We are 90 percent on the statements although real objects inside of here. And this is what we really want to test. So let’s see here. Now what we want to do is describe after click person function. So let’s talk about testing.

There are really 3 basic steps here. Arrange, act, and assert. The 3 As. So our arrange here would be any variables to create or pass in. in our case here in our people directive we actually do we have a person that we are going to then want to do a one nose alert on that. Alright so in our case here for our arrange we want to var person=and name is bob smith. Great so now we have a person object. So now we want to act. So now we want to say vm clickperson and I want to pass it to person. Great. And then I want to assert. I want to expect that some action is happening. So now what’s interesting in here is we are doing a really bad thing here. We are calling this alert and we code mock that out and do sign on and do a spy and do all this sort of stuff and we are really doing a simple thing is we know this isn’t going to stay here let’s just go ahead and change this out and use what we already know. And let’s go ahead and use logger info and bring that over here and I’m just going to place. We are just going to have it logged for person object.

Now the one challenge here is now we do need logger injected. It needs to be here.and when we come over here to the spec and whenever we talked about the inject here that this is where we add any dependencies. Well this is a dependency so we want to go ahead and eject that. So undefined is not an object evaluating vm click person. Got it. So in our case here vm is not what we think it is. So we have some sort of issue with it. Well we will figure that out in just a second. Excellent let’s see. That’s going to take a second vie seen this one before. This is going to be a ton amount of coding here. So in our case here we are doing logger info. I believe the problem is we don’t actually have logger. It doesn’t know how to inject it. It is the bigger issue here I believe is what is happening. If we go look these blocks logger he is part of the log block logger module. Define here. Let’s go ahead and copy him and now let’s go to our directive people module and it doesn’t have any dependencies.

Let’s go ahead and add this guy. And although that didn’t seem to fix it. I believe what’s happening, go back over here. Let’s just do a quick console log (person). Save that. Let’s see do we have a log here. That’s the person great. Let’s do it on vm. It’s undefined. However this setup is defined so let’s move it up here. Excellent. This is actually not getting executed. It is here appears to be happening. We notice because if we take this all out we get 40 of 40 ran and we got the people controller and you can see a person is on there. Alright great so we put this in and we don’t run any tests and were just getting in here directly from here. So what appears to be happening is that this is running before.

So what happens here is the describe actually starts kicking off the tests or the describes are run before the it’s and before the beforeeach. I incorrectly built this test. So all we need to do is add an it. Now if I put this inside. What happened there. I grabbed too much. Grab this now paste it. Great. Now if I run it. Excellent now we have it and everything passed. Now in our case here though when we started we didn’t sort anything. We want to change that. Come back over to our controller spec and we want to see, we want to copy this spec space here we are going to bring it over to the people directive spec and we are going to insert that log info to match bob smith. And now let’s run it. Not able to find variable log. So now we just inject a new variable.

We go back over here where we copied that from and we can see that one of the other items that it did inject is $log. So just copy this guy and bring him over to our people directive spec. excellent. Now there. Great! Save it. Now if we come back over here refresh it. We are at 100 percent. We want 100 percent. Excellent so in conclusion there’s how we write our tests. All being a couple little glitches there be sure to make sure to inside of your describe. Describes create your structure for your tests. Test themselves using the inside of the it. We could have removed a couple things like this outside of it I believe and we can test really quickly and just make sure. Yes it still successfully runs. No problems.

Just make sure that you are using and it before you go ahead and do this. Also if this was an ac operation it would be a $rootscope $apply and that would allow a runtime to execute and complete and that way we could assert that this actually got done. So with that there is our conclusion for refactoring some new component based directives. On the test for news and our container they are very much the same so we are not going to go through and do those. Our next video of our series will be on type script. That will be the next logical step in our application for angular 2.0 thank you for joining u

Please enjoy, learn, subscribe, and like our channel on YouTube.

We would love to hear from you so don’t hesitate to share your ideas or provide us with constructive feedback.

BrieBug Solutions a Denver based website and mobile application development agency that specializes in Angular and Full Stack development. If this is a technology that you would be interested in to boost your business, feel free to contact us so we can get you started on your vision!

  • Contact Us
  • Telephone: 888.679.2201
  • Address:
    BrieBug |
    12596 W Bayaud Ave Suite 201 | Lakewood, CO 80228