Large Scale AngularJS App

December 18, 2015

My list of how not to completely screw yourself over on a large-scale AngularJS project – The biggest project I’ve done has gone from Angular 1.0.x to 1.4.x. These are what my findings were:

  1. Setup the style guidelines right from the get-go. Seriously, this simple starting point will in the end give you at least the advantages of keeping code clear. John Papa has a community driven one on github that’s excellent.
  2. Get comfortable with directives. Review the way that some of the more popular ones are setup and created. DRY is your friend in any application, and doubly so in a large one.
  3. Be sure that everyone that is going to be working on the design end of it (CSS, LESS, SASS, etc.) are capable of the work. The more complex the CSS of the site, the more potential to royally screw up the UI there will be.
  4. I suggest having everyone watch at least the JavaScript Good Parts video with Douglas Crockford. It’s available on Pluralsight and I think Frontend Masters.
  5. Setup your Linters from the get go. JSCS and ESLINT are my preference. I also highly suggest Uncss and Stylestats for the UI CSS work that’s being done.
  6. Consider a LESS or SASS Library to standardize some basic mixins to use throughout the UI.
  7. If possible, get at least Directive unit tests working properly. It’ll save you many debugging headaches.
  8. Be sure to well document an actual snippet for your directives for use in a top of file comment block. Nothing more annoying than needing to use a random directive that requires you to read all the code to know how to use it properly.
  9. Most browsers work properly most of the time, until you open things in IE.
  10. Get auto-deploy setup to dev servers. Makes having the latest builds available to QA a lot easier when somewhat centrally managed.
  11. If you use $broadcast just throw your computer out of the window.
  12. Don’t roll your own translation directive. Use angular-translate or another community option.
  13. Get used to arcane console.log errors.
  14. If you encounter your app having infinite digest cycle errors, you’ll realize very quickly that they’re not easy to diagnose. I highly suggest reading my post on finding them in a large app and what worked for me.

I may add more to this list in the future – but have fun and make cool stuff!

Absolute Positioned Textarea Text Not Appearing

September 15, 2015

I’ve been doing a LOT of CSS with my projects as of late, mainly with SASS and LESS, but that isn’t related to this issue.

In creating a popover textarea entry directive, I got all of the CSS in place and then noticed that for whatever reason the textarea wasn’t showing any text that I entered into it.

It would appear if I toggled any of the CSS properties in the Chrome Dev Tools, however, my issue remained. If I removed the position absolute, it would work. I was clueless as to what would resolve this, but at least I could see changes when modifying stuff.

And then I noticed, I had wrapped the outermost tags for the directive in <span> tags like this:

When I set the <span> tags to <div> tags, voila, everything worked as I had intended. After looking into it further, I realized that the span tags only should be used for inline-level components, and I was using <div> elements inside of the <span> tags, which are block-level elements. As a result, the <span> tag breaks the html in that it doesn’t allow block-level children.

So if you run into an issue like this, check the surrounding tags. Here’s a W3C detail on the span tag for those interested in further technicals: http://www.w3.org/TR/html51/semantics.html#the-span-element

MEAN Stack – Full Test Sample Application

August 28, 2015

In order to help the development community at large, I thought I’d push out the app that I had used in my write up for testing the MEAN stack. You can check it out on github here: https://github.com/SBero/mean-todo

It still has some work needing to be done to it, but enough is currently done to help others get started with fully testing their MEAN apps.

I’d like to get it to the point, where it’s the perfect sample project for someone new to the MEAN stack to be able to review, pick up some best practices and see exactly how to do the testing that’s involved (especially testing all of the isolate scope parts of an AngularJS directive!).

AngularJS Multiple Identical API Calls

August 11, 2015

With a large AngularJS application, and even smaller ones, you can run into this issue where you end up with multiple identical API calls being made if your using the $q service. This occurs because there is a conflict with overlapping calls, which basically re-try the last API call for all of the call conflicts.

This happens when you aren’t bundling all of the calls up with the $q.all() function. This function receives an array of $http service objects that will resolve to an array once they’re all returned from the server.

You need to pass into the $q.all() function http promise objects which can be retrieved from the $http service.

For example:

Eliminating the .then after the $http and doing just  return $http(req); will get you the promise to add to the array which you’ll pass to $q.all().

Unit Testing Full Stack Part 2 – AngularJS Part 2 of 3

July 26, 2015

This is part 2 of 3 unit testing full stack javascript. In this post we’ll talk about testing some more of Angular: Services, Directives and Filters.

In case you missed it, this unit testing series of posts are:

Part 2A – Installation, Routes, Controllers

Part 2B – Services, Directives, Filters

Part 2C – Coverage Reports, End to End (e2e)

So let’s get started with where we left off, testing services.

Services

Testing services is actually fairly straight forward. The thing to keep in mind is that you intercept all the requests that would normally go to a backend, and return the status code, etc. that you would expect.

Let’s break down one of the unit tests:

As you can see the $httpBackend is where we describe the type of http call that the service will attempt to do, and we setup how to return back to the service. You can send data to the $httpBackend, having it expect a certain set of data, or have it return specific data to further test the directive. The link to the Angular Site for $httpBackend will help you read about the different ways to utilize it.

Once we call $httpBackend.flush()  we flush all pending requests and respond with the pre-determined responses.

Moving further, you can obviously test any of the functions inside of a service quite easily. Services I would say are one of the easier components to test in Angular.

Directives

I thought that directives were actually one of the components in Angular that I had the hardest time trying to figure out how to properly test all the aspects of. It seems that most people never get into actually testing all of the pieces of them.

Let’s just get into it: isolate scopes are in the vast majority of directives, and most places that show you how to test directives, don’t really specify how to test those.

I’m here to hopefully clear that up. Lets look at en example directive and it’s corresponding code.:

TODO Directive Items

When the user clicks edit, it sets $scope.editing  flag to true, and gives them this view:

MEAN Todo Directive - Edit Mode

So with that in mind, let’s make a directive unit test that allows us to test those isolate scope functions, check the variables on it, and do a save to the API (intercepted with Mocks), and attempt to do things that give back errors and allow us to accommodate for that.

That’s quite a long set of unit tests, well, 8 of them to be exact.

Do you remember when we setup the testing in Karma, we added the html2js pre-processor? That’s what allows us to load the html template file in the unit test with this piece of code:

To test any bits and pieces of the isolate scope, you need to do this:

We need to call elem.isolateScope()  on the compiled element, digest the scope, so that we get updated and bound scope items. Now with the elemScope  variable that’s returned from calling elem.isolateScope()  we can access any of the isolate scope items, functions, etc. as you can see here with the call to elemScope.editItem() .

Everything else is pretty typical standard stuff relating to testing of services with $httpBackend  and doing a flush()  to validate that the api call is being made and to test different return scenarios (http status codes).

Filters

Testing filters is really quite simple. You would basically invoke them as you would in a controller, testing the return results. Here’s an example:

So that takes care of our 2nd part for testing Angular JS. Please let me know if you have further questions, so that I can enhance the post for others to learn from.

Our final post on Angular testing we’ll discuss coverage reports and End-to-End testing with Protractor.

Lessons Learned: Upgrading an Enterprise Angular App from 1.2.x to 1.3.x

July 23, 2015

I recently completed an upgrade for an Enterprise Angular app from 1.2.24 to 1.3.15. Doing an upgrade on a large system is no small undertaking. Finding solutions to resolve upgrade incompatibilities can seem like a bit of black magic at times. This upgrade was no exclusion to just that.

The most common error I got was Error: $rootScope:infdig Infinite $digest Loop. Staring at these errors in the console all I could think about was how on earth was I going to fix them?! With a codebase that’s more than 45k lines for just the front end, I start questioning if I’m going to be able to even do this, if I’m a good enough developer, etc. The typical Imposter’s Syndrome that’s so prevalent in this line of work.

This error typically gives you 0 hints what’s causing it, and where it’s coming from, but I found some resources that helped me realize that anything that has a watcher needs to be Idempotent in AngularJS. If it’s not, it could be the source of an infinite digest loop.

So I thought rather than make a long write up of all the different pieces I solved in my project, I thought I’d supply the main resources that I had to read and understand in order to solve different errors. Let’s face it, all projects will be different, but the overall upgrade challenges I’d assume are going to be relatively similar. Here’s the list:

Scope Work

http://stackoverflow.com/questions/13743058/how-to-access-the-angular-scope-variable-in-browsers-console

https://github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()

Infinite Digest

https://github.com/angular/angular.js/issues/705 (Idempotent – Important to know for usually fixing Infinite Digest Errors)

http://stackoverflow.com/questions/20567614/errors-in-angularjs-often-causes-infinite-loops

http://stackoverflow.com/questions/17466872/infinite-loop-with-angular-expression-binding

http://stackoverflow.com/questions/21322755/tracking-down-infinite-digest-errors

http://stackoverflow.com/questions/24592283/angular-infinite-digest-loop

Filters

http://stackoverflow.com/questions/25877704/what-is-stateful-filtering-in-angularjs

http://stackoverflow.com/questions/27402326/angularjs-1-3-async-filter-not-working

Grep/Ack Tricks

http://stackoverflow.com/questions/9081/grep-a-file-but-show-several-surrounding-lines

Enhanced performance is a major upgrade that you get when going from 1.2.x to 1.3.x. If you make sure your filters aren’t stateful and you start setting up all two-way data bindings that never change to use the ‘::’ one time binding syntax you can quite easily supercharge an app with performance issues. Feel free to connect with me if you have any particular difficult bug that you’re trying to fix during an upgrade.

Unit Testing Full Stack Part 2 – AngularJS Part 1 of 3

July 16, 2015

This is part 2 of my multi part guide for setting up and testing a full stack JavaScript application. Next up is AngularJS. I’ve broken this up into 3 separate parts, as this is a bit more complex for testing the front end, since we have both unit tests and end to end tests. The parts will be broken up as follows:

Part 2A – Installation, Routes, Controllers

Part 2B – Services, Directives, Filters

Part 2C – Coverage Reports, End to End (e2e)

Installation & Configuration

To get started, install the following:

Karma (test runner) in conjunction with Jasmine (unit testing framework). You can use other unit testing frameworks, if you so desire, just check here, under ‘Framework’, to see which ones are compatible.

So let’s start with our AngularJS project, with npm, it will install both karma, the jasmine plugin and the chrome launcher plugin, as well as any required dependencies for those packages.

Something to be aware of, is that because Angular runs in the browser, it requires the chrome browser to launch when running tests, so that they can execute. This will launch and destroy a chrome browser for you automatically, but if you’re not wanting to have a browser launch, you can use PhantomJS for everything to be just run in a headless browser (A browser engine without any graphical interface, it runs in memory only).

Once these are complete, you’re next goal is configure karma to run through the tests for us. To do this, we need to create a configuration for Karma. Navigate to your /test directory and we’ll type (where karma-unit.conf.js is the name of the configuration file):

You’ll be asked a series of question (see here), once done, you will inevitably go into the Karma configuration itself and setup the correct order for loading your project files under the ‘files’ property array. This will probably take looking at your own projects index.html file and making sure that the files are all there and in proper order. Everything source file that you use in your project will need to be loaded this way, and again, in proper order.

To do the unit tests, you will also need to load the angular-mock file. This allows us to mock the backend requests over http, as jasmine doesn’t actually process async calls to an api properly. So be sure to add that file to your files array. Here’s a link you can add to the array for the angular-mock.js file form the google api CDN, for v1.2.26:

My files array looks like this:

As you can tell, it has some wildcard symbols there, where ** means all sub-folders and * means all files, and in my file, *.js means all files ending in .js. So these are all of the files included in the testing.

Next up are the plugins. My plugins looks like:

I have a few extra karma packages installed, if you’d like to use them, you can npm install them. karma-ng-html2js-preprocessor makes it possible to inject a directive template into the tests for testing. karma-mocha-reporter is the type of report that gets generated that I like, and finally karma-coverage is a coverage reporting tool built on istanbul.

Finally, here are the preprocessors, reports, and coverageReporter configs:

I need to configure the preprocessor details for both ng-html2js and the coverage plugin, and configure the coverage reporter output details.

Finally, we’re ready to start writing some tests.

Once we write tests, we can run the tests by typing:

Routes

I have my route test spec file in /test/unit-angular/routeSpecs/routeSpec.js.

I need to create the file just like any typical mocha test, with the describe, beforeEach, it, etc. functions. So a very basic route spec file will look like this:

Going through this, is pretty straight forward. we need to inject the different services location, route and rootScope. The inject function also ignores the surrounding ‘_’ for the service names. This is just to help readability within the test file. Now we can use these services in the tests themselves.

Any request made to any server requires us to use the $httpBackend to intercept the expected call and return what response the that should be expected.

In order to navigate, you need to use location.path(…) and follow it up with a manual call to $digest().

This is pretty much the entire pattern for testing your different routes. If your application requires you to login in order to test routes, you will need to create the objects, etc. to simulate a user logging. Remember, since it’s not actually making any calls to a server, you don’t need to worry about a token being authenticated, etc. Those kinds of tests should be run as unit tests against the API and/or end to end tests.

Controllers

I place my controllers in /test/unit-angular/controllerSpecs/<ctrlName>ControllerSpec.js.

Testing controllers is also fairly straight forward, but requires understanding a few important concepts.

1) We have to manually create and setup the scopes for the controllers we want to test.

2) You need to perform $httpBackend.flush() after we want to perform the $httpBackend calls in controllers.

Here’s a sample controller spec file:

The beforeEach is a bit more complex for the controller:

As you can see, I create the new controller and bind the scope to it by first creating the new scope with $rootScope.$new() and then setting it for the manual dependency injection with the $controller service {$scope: scope}.

Following this, I prefer to test all of the functions in a controller to be sure that they’re defined before I start testing them.

If the application is refactored, just realize if the function changes name or is removed, you’ll need to keep your controller test files current.

Finally, testing the actual scope functions is required. You’ll need to setup any $httpBackend expected calls first before you test the scope function, otherwise you’ll get errors for unexpected $http calls.

 

Any required objects for the scope function should be passed in at this time as well so that the function runs properly.

You can see how in the one test I try and use an empty object, and what I expect the api to respond with.

The rest comes down to just writing test coverage for all of your controllers functions based on different scenarios. Time to write your test plans! 🙂

Next part in this series we’ll cover the Services, Directives and Filters. We’ll go in-depth with testing Directives, importantly, for how to test their isolate scopes and functions.

I hope you enjoyed the read, and let me know if you find any issues with the above so that I can edit any mistakes.

AngularJS Error: $compile:multidir Multiple Directive Resource Contention

May 12, 2015

I recently had been working on an upgrade from 1.2.x to 1.3.x branch of AngularJS for this project I’ve been working on.

While doing this, I got this error:

Clicking on the link the Chrome console brought me to the AngularJS page giving me more details on the error thrown. It said that two different directives had a conflict with each other.

However, the code snippet gave me about 0 details, and the information was still, while something, a bit archaic.

The notes on the page mention to do a few different things to resolve it:

I checked the first scenario, and it wasn’t the case for the directive. I removed the third scenario, and it still was thrown. Next I checked to see if there was a directive naming conflict with ack:

Scrolling through the list to look at the filenames, I noticed that a third party library had the exact same name as one of my directive names. Building the library to not include that filename resolved my issue, and after a few more bug fixes, I successfully upgraded my app to the 1.3.x branch. It’s a LOT faster! I highly suggest upgrading your app as soon as possible.

If you would like to read the full write up of lessons learned which includes more of the issues I ran into, as well as a pretty solid list of the different resources I used to resolve many of the upgrade issues read this post: http://www.stephenbero.com/lessons-learned-upgrading-an-enterprise-angular-app-from-1-2-x-to-1-3-x/

Node/ExpressJS Can’t Set Headers Bug…Possible solution

February 1, 2015

I was working on some of my more complex project aspects today, after spending an entire weekend setting up, and building out most of my applications unit and end-to-end tests when I noticed this issue when I moved onto the new build features inside of the Angular app:

Possibly unhandled Error: Can’t set headers after they are sent.

I’m scouring the code EVERYWHERE. How is this possible? According to my unit tests, I have code coverage across all of these functions with literally every permutation of tests imaginable, or did I???

Upon further inspection, I noticed that my AngularJS front end was making two identical calls to my API. This simultaneous connection request was enough to throw the error in the Node/ExpressJS backend.

tl:dr; – Check to be sure your AngularJS / Front End isn’t making simultaneous calls incorrectly to your API/Backend.

JavaScript Design Patterns

December 9, 2014

While in the process of needing to add some more complex functionality to my current ordering system project, I knew that I needed to start tackling the implementation for a number of design patterns for the front end. I finally took the time over the weekend to sit down and learn the ones that I needed to use and incorporated them with a basic AngularJS/Bootstrap/JQuery template.

Removing everything but exactly what I was trying to accomplish made understanding and implementing the patterns much more reasonable, as well as efficient.

I created a github repo to put them into in the event anyone else is looking to actually learn some design patterns in JavaScript as well. Check it out here:

https://github.com/SBero/JavascriptPatterns

I’ve so far implemented the following patterns:

  • Factory
  • Command
  • Memento
  • State
  • Strategy
  • Visitor
  • Chaining
  • Lazy Load

Hope this helps anyone out there looking to implement the same things themselves.