Using Stubs and Mocks in Jasmine to test your Angular code

Setting up your environment and is a very important part of unit testing AngularJS code. We discuss some of the tools and methods under which we can provide the full workflow of a system under test in this post.

Intro

Unit tests allow us to automatically test our code under a variety of conditions to prove that it works and when it breaks it does so in expected ways. In order to predictably test code, we also need to completely control the setup and data provided to the code under test.

Thankfully, the test tools provided for Angular testing allow you to mimic your models and control how your code responds to code in a very precise way. Jasmine provides some easy way to create test doubles and even “spy” on their execution.

In this post we will discuss some of the best practices and tools we use to control the environment your code is working against.

Why do we need to fake stuff?

We need to control the entire environment and workflow to make sure we are testing the exact scenarios.

Messing around with the DB and creating fake records can be difficult at best, at worst it can create false positives. Even more common, some CI systems lack access to a DB at all

We also need the ability to re-create the conditions under which a bug has been created. sometimes this means we need to replicate some crazy conditions

There are two tools to make this happen: Test Stubs (also known as  Fakes, depending on who you ask) and Mock Objects:

  • Test stubs are a very simplified object or data structure designed specifically for the test scenario. These can be constructed at the beginning of the test or per test.
  • Mock objects are class instances that mimic an existing class to provide the same method interface and return specific values when a method call occurs.

Test Stubs in AngularJS & Jasmine

Test stubs are a simple data structure or model we rely on when running our tests. These can be as simple as a static array of data or a very lightweight object with publically scoped methods. To differentiate a stub from a mock, we typically only mimic the methods we are actually testing. This is quite useful during

More often than not a stub is created at the beginning of the test suites and made accessible to the suite’s tests. A good practice is to limit the modifications to the stubs to make sure you are always testing the same thing.

If you must make changes it is a good idea to make a local copy to isolates your modifications to a specific test.

Test Stub Examples

HeaderComponent

Below is an abridged version of the component code we are unit testing. The important thing to note: at the end of this method’s execution we make a call to the router service to navigate the user to the “login” route and we need to make sure this and only this method is executed.

/**
 * Simple component providing a navigation header.
 */
...
export class HeaderComponent implements OnInit {
    ...
    /**
     * clickLogout clears the user's creds but also 
     * takes the user to the Login route
     */
    clickLogout() {
        ...
        this.router.navigate(['/login']);
    }
    ...
}

Test Suite Code

Here is the abridged test suite where we create our test stub

...

/** 
 * beforeEach setup executes before each test suite test runs.
 *
 * This allows us to setup the stub before each test
 */
beforeEach(async(() => {

    ...
    
    TestBed.configureTestingModule({
        ...
        providers: [

        /**
         * Create a very basic stub object with one method:'navigate'
         *
         * Use Jasmine's createSpy to create a very basic function
         * which also allows us to "listen in" when it's called
         */
        {
            provide: Router,
            useClass: class { 
                navigate = jasmine.createSpy("navigate"); 
            }
        }
        ...
    ]})
    .compileComponents();

    ...

}));

/**
 * Here we test the method and make sure we actually navigate
 */
it('should navigate to /login when clickLogout is fired', () => {
   ...
   let router = fixture.debugElement.injector.get(Router);
   component.clickLogout();

   // "listen" to make sure that the navigate method has been 
   // called and it was called with the expected value
   expect(router.navigate).toHaveBeenCalledWith(["/login"]);
   ...
});

 

Mocks

A Mock object is a simulated object instance used to mimic a classes behavior using the same interface. In simpler terms, this is a fake class with the same method signature as the Real Thing.

A mock object can be composed of multiple objects (and sometimes multiple mock objects), but most often should be created as simply as possible to keep your tests easily maintained.

Mock Object Example

/**
 * Create a mock of an existing service
 * by simply extending it and overriding some 
 * of the methods you wish to use in your tests
 */
class MockAuthService extends AuthService {

    /**
     * This method is implemented in the AuthService
     * we extend, but we overload it to make sure we
     * return a value we wish to test against
     */
    isLoggedIn() {
        return false;
    }
}

...

beforeEach(async(() => {

    ...

    TestBed.configureTestingModule({

        ...

        providers: [

        /**
         * Inject our mocked service in place of AuthService
         */
        {
            provide: AuthService,
            useClass: MockAuthService
        },

        ...

    ]})
    .compileComponents();

    ...

}));


it('should navigate to /login when clickLogout is fired', () => {

   /**
    * Get the mocked service here from our fixture
    * and add a spyOn over-ride to pretend we have
    * a logged in user.
    */
   let service = fixture.debugElement.injector.get(AuthService);
   spyOn(service, 'isLoggedIn').and.returnValue(true);
   
});

Conclusion

Unit tests are only as good as the environment you can provide for your code under tests. It’s very important to be able to mimic and recreate the environment under which you have both positive and negative results for your code.

Angular 2 Routing

Angular 2 Routing is bit complicated when compared to routing in Angular 1.x but it is very powerful. We hope to clear up some of the common confusion when setting up routing and provide some practical examples as references.

Understanding routing in you application is the key to creating a single page application. Routing is what allows view navigation in your application like ‘detail views’, end user bookmarking and even allows you to set up a ‘logged in’ version of your applications views.

Routing isn’t included by default in Angular 2, in fact you have to explicitly include it as a library. I also will say, it’s not incredibly intuitive to configure. We’ll take some time to explain the history of the router and dive into some of the basic concepts.

Basic Concepts of Routing in Angular 2

Router Library

The router itself is implemented in the optional Router Module, which is kept separate to keep the base library size low. Include it in your main module like this:

import { RouterModule } from '@angular/router';

...
@NgModule({
 declarations: [ ... ],
 imports: [
     RouterModule.forRoot(routes),
     ...
 ],
 providers: [ ... ],
 entryComponents: [AppComponent],
 bootstrap: [AppComponent]
})
export class AppModule {

}

Base HREF

The base HREF is the starting point for your application and is used to create your home route. It’s this starting point that your browser will also use to create a history to prevent ‘breaking the back button’ which is always a sticking point in SPAs.

Here’s the syntax you need to add to you html:

<base href="/">

Configuration & Routes

const routes = [ 
    // Default, or home, path. This matches your Base HREF
    { 
        path: '', 
        component: HomeComponent 
    }, 

    ...

    // Wildcard, or the 'catch-all' route pattern. If the requested
    // route does not match anything above, this route is displayed.
    { 
        path: '**', 
        component: HomeComponent 
    } 
];

Resolves & Guards

Resolves are services that must be completed before allowing the route to be accessed and loaded. This is how we can ensure that the data is available for the route prior to allowing the user to access the route.

A quick example of this would be a UserResolve class that retrieves a list of users before displaying the route.

Guards are a method to prevent a route from being accessed unless a certain state is met.

A quick example of this would be a LoggedInGuard class that prevents a user from accessing a route unless they are logged in.

Child Routes

Child routes are a way to add specific routes to a feature.

Example 1: A One Route Application

Below is an example of an application with a single route. This illustrates including the router module, a base href and a very basic route configuration.

Example 2: A One Route Application with a Resolve

Below is an example of an application with a single route that requires a service to resolve a data retrieval before rendering.

Example 3: A multiple route application with a child route

Below is an example of an application with two routes and a child route.

Conclusion

While it may take some time to completely wrap your mind around routing in angular it’s clearly an important part of creating a real SPA. Don’t be afraid to take and reference your own notes!

Providing data via Angular 2 Services

Interaction with data in Angular 2, internally and from external sources, is based around the concept of services. Learning more about services is integral to learning how to create an Angular 2 component or application.

Angular 2’s biggest strength is the reliability of encapsulation and re-use, which means passing data to and between components can be a pain at first. You are highly discouraged from getting data from the DOM, making AJAX calls in your components is a no-no. How are you supposed to get data to your things?

This is where you start to use Angular Services. Services are an injectable class that allows you to keep all your functionality in one place. Here’s the official definition of a service in Angular 2 from the docs:

A service is a class with a focused purpose. We often create a service to implement features that are independent from any specific view, provide shared data or logic across components, or encapsulate external interactions.

You have data you need from an AJAX endpoint? Create a service.

You want to maintain state for an object that multiple components? Create a service.

Want to do anything cool with some data across your application? Create a service.

For those of you familiar with the pattern, Services in Angular 2 are really Singleton Service models. Its a single instance you pass around. It has a state, it has some methods. Its easily mocked and you know where the ‘meat’ of your application is at all times. It allows you to move the data manipulation out of the display code entirely.

Coming from a Vanilla JS background all of this may seem a little over complicated. While simplicity is something to strive for, there are good reasons for this level of abstraction:

  • Encapsulating the functionality of your services is a good practice
  • You can focus on functionality in your components with a well defined service
  • Mocking a service is easier than mocking an environment

Here’s some examples of services in action:

Example 1: A Simple String Returning Service

This is an example of a simple data service providing some data to a component. While extremely simple, it shows how to get data ‘into’ a component from an outside source:

The component itself relies on the service to provide the data to the front end. The value of ‘bar’, displayed in the component’s template actually comes from the service itself. When the component loads, it calls the “getBar” method of the service which returns a simple string.

While this example might seem very trivial, it lays some groundwork for the other examples. A service provides data external from the component in an ‘agreed’ upon way. This contract allows us to take some control of how we get the data away from the component, which should really just focus on how the data should be displayed.

Example 2: A service that allows us to share data between more than one component

This is an example of a service that allows a total of three components to interact together.

If you look at the code in the example, this small ‘app’ has three components that each include the CounterService. This extremely simple service allows us to interact with a single integer variable that can be incremented and decremented via two completely separate component’s buttons.

Again, while maintaining a ‘contract’ we can allow each one of these components to focus on the display and events rather than the actual manipulation of the data.

Example 3: A service that provides data from an AJAX (external) source

This is an example of an AJAX service providing data to a component. A ‘locally’ hosted JSON file is retrieved via AJAX in the service itself and then sent to the component. This component is able to interact with the data entirely through the service itself. This level of abstraction allows the component to strictly focus on the display and styling of the data provided by the service.

 

Promises vs Observables in your AJAX services

Promises are great and a well trod subject, I’ll leave it up to you to read more about their benefits (or you can revisit my previous blog post: http://blog.arroyolabs.com/2016/04/angularjs-2-ajax/). Observables, when compared to promises, allow you to specify not only when something is ‘done’ but when something has changed.

This most definitely comes in handy when you create a service like the example above that allows you to detect when any changes occur from your service.

A Final Note

While the final architecture of your application or bundled component is really a choice you need to make, I hope we were able to clear up some of the basics of using services in Angular 2.

 

End to End testing your Vanilla JS App with Protractor

ProtractorJS is a robust and easy to use e2e test framework specifically designed for testing AngularJS applications. With some simple edits and a slight change in thinking, you can also use it to test your non-angular web apps and provide some sanity to your testing strategy across projects.

ProtactorJS is an end to end test framework from Google used to test AngularJS Apps. While similar to existing tools like CasperJS, ProtractorJS is specifically designed for use with AngularJS.
With minimal effort you can use Protractor with your Vanilla JS web app as well. Why would you do this?
For one, using the same test framework for all you apps provides some sanity to writing tests for all of your projects. And you can’t honestly tell me you have all your apps converted to AngularJS already.
Second, it’s gaining popularity and for good reason. It’s a solid testing framework and is relatively easy to set up. Also, it has the backing of a very well known company (cough cough, Google) so it will be around for a long time.
Finally, it’s use of Jasmine and suite structures allow you to write some flexible tests. Encapsulate your logic, group stuff in ways that make sense. No more fragile tests!
Enough stumping, let’s get to the parts you actually care about.

Installation and Set Up

While I’ll point you at the official docs for installation instructions, I’ll provide the basic elements required to installing and running your Protractor tests:
  1. Protractor, Karma & Jasmine
    • Clearly, you need to install Protractor
    • Protractor uses Karma to connect to Selenium
    • Jasmine is used as the testing syntax.
      • You can use other frameworks, but my preference is Jasmine.
  2. Selenium Server & Webdriver
    • Protractor interacts with your tests using Seleniums Server and Webdriver. You can run Selenium locally or use a hosted service like Sauce Labs.
    • Local installation and setup is turn key simple using NPM.
  3. A Web server
    • Since your tests use a real browser to execute, you need a host of some kind.
    • It’s entirely possible to run your tests against an external server (like your staging server), but in practice I like to serve locally. In our example I used the local-web-server NPM package.

Protractor Test Concepts

Again, I’ll point you to the main documentation for longer descriptions of the concepts, I wanted to point out some that need to be discussed when prepping your protractor tests for execution on your VanillaJS app.

Config File

A config file sets up some required variables and tells Protractor how to run its tests. This includes a directory where your tests are held, the testing framework you use to write your tests and the address to the selenium server instance you use to run Karma.

Spec File (Test Suite) – “Describe”

Test suites are groups of testing conditions that focus on a particular section or part of your application. Using Jasmine, these are structure with the “describe” function and a brief string indicating the portion of the application under test.

Test Hooks

Hooks are small functions that are called during test executions. An example is the beforeEach hook we use to set up our tests for use with non-angular code. See the note below on exactly what goes in this hook.

Test Blocks – “It”

Test blocks are identified by an “it” phrase that describes in simple terms what you expect to happen. This is useful for turning user stories into tests like “User Registration Form should validate user input”.
These test blocks do have some minimal setup but are mostly for performing actions and asserting values. Check out our example code to see some of this in action.

Page Objects

Page Objects are similar to test fixtures in other testing frameworks, but thats underselling the usefulness of this concept. Page Objects are small JS objects where you can encapsulate and abstract out common page elements and share between your tests.
Use these to abstract out some commonly tested things, like getting the text or value from a page element. If you use your page object in all your tests, you only have one place to update when a change is made (instead of having to update ALL your test suites).

Running Protractor on your Vanilla JS App

Like we noted above, Protractor was designed for testing AngularJS apps by default. A large difficulty in e2e web app testing is knowing when something has rendered on the page and is ready to have some interaction. AngularJS abstracts how you work with the DOM in JS as well as having some control over how something is determined to be “ready” using Zones.js.
Three major things need to be done to make sure your Protractor test will actually work with out Angular:
  • Expose the web driver in a way you can access the DOM for interaction.
    • Due to the nature of how Angular abstracts the DOM and how it takes over all the app’s event cycles. We need to expose the Selenium Web Driver in a way you won’t hate.
    • Add this line to your onPrepare hook in the config file to assign the web driver to an global variable called “dv”
      • global.dv = browser.driver;
  • Tell the test not to wait for Angular to give the “go ahead, I’m ready” signal.
    • Protractor uses Angular to tell it when the page under test is ready to be tested. We need to skip this in order to test our non-angular app.
    • Add this to each test suite’s beforeEach hook to make sure the test knows to run as we expect
      • dv.ignoreSynchronization = true;
  • Start thinking about your tests with Promises
    • While I’m sure most of us at this point have seen and used Promise style functions. When testing an Angular app, using the default locators is easy. Since we are testing our app using the native web driver, we need to use a promise to allow Selenium to return the DOM element itself. Really though, it’s not that tough.
    • Here is an example where we want to assert the value of an element with the css ID of “foo” using a series of chained promises.
expect(dv.findElement(by.id('foo')).getText()).toEqual(“Bar”);

Plugin – Protractor Utils

Protractor does indeed have a very basic plugin system that gives end users some ways to extend base functionality. I’m still trying to understand this system myself (I haven’t figured out how to use a plugin that isn’t globally installed) I have found one that is very useful called jasmine2-protractor-utils.
I’ll leave some of the longer explanation of this plugin to the author, but my favorite feature is the ability to take a screenshot of the browser in the test on suite or block failure. Once you get things up and running so your tests are running automatically, having some visual artifacts of a failed test will help you replicate and diagnose what and how things went wrong.

Example – Movie Vote

Here is an example (very small) Web App demonstrating a very basic suite of Protractor tests. You can simply clone this repo, install the required packages using the package.json file and run these tests. Simply follow the instructions in the README.md file.
https://github.com/arroyolabs-blog/movie-vote-protractor
For an example of an intentionally failing test, check out the `mv-home-fail.spec.js` test in the tests directory.

AngularJS 2 & AJAX

Intro

The AJAX paradigm really launched the web into primetime some 10+ years ago, but now its almost expected. Now it’s a ubiquitous part of the web landscape. Most web apps now resemble an ‘app’ in regards to their UX and users ‘expect’ content to dynamically update without a page refresh. In the past, we have used some great tools like jQuery to cobble together a basic app to interact with our page and an AJAX backend, but a framework like AngularJS adds some sanity and structure to what could have been a mess of spaghetti code.

The most common use cases for AJAX are dynamic content and form interactions. For example, if you have a large list of tabular data, you can load it via AJAX to show your basic page to a user without having to render the table on the server. Forms can be validated with JS and sent to the server in the ‘background’ so the user doesn’t have to leave the page. There are MANY other use cases for AJAX, but I think this covers the majority you will encounter when developing a web app.

HTTP / XHR

Most browsers you will encounter, or your clients will use, will have access to the HTTP API known as XHR (it’s safe to assume that anything above IE 5.6 will allow you access to this API). While some browsers offer Fetch support, I will skip that for the purposes of this blog post.

AngularJS Services

In general, you will provide AJAX access via a service. Services are a part of the Dependency Injection patten that makes AngularJS so modular. Creating a piece of code that allows you to encapsulate all actions that make AJAX calls allows for better re-use and easier testing.

Observables vs Promises

Too often used tools/patters for working with asynchronous data structures are Observables and Promises. While you may be familiar with Promises as a pattern, and most likely have used something like promises in the past, Observables are a pretty new concept to me.

In short, Observables are “a push based collection” using the observer pattern. Put simply, this is a queue of objects with some amazing manipulation methods and hooks to allow you to detect when something occurs within the queue. It’s pretty great for dealing with a dataset that needs to be lazy loaded or can possibly get updated in the life cycle of the application.

Here is a simple example based on the angular.io Hall of Heros example showing an observable request:

image

A promise is “a way to define actions or computations once an async event completes”; an observable is “way to define computations or actions that happen when one or more events in a stream occur”.

Here is a simple example based on the angular.io Hall of Heros example showing an promise based request:

image

The key take away from comparing these two tools: observables and promises are both great tools for async programming like AJAX, but observables are more like a stream of data than a ‘one time request of data’. We’ll touch more on this in future blog posts.

Here are some code examples that borrow very heavily from the HTTP Client example found on the Angular.io site.

Code Example: Promise

http://plnkr.co/edit/aB69cfM5soJzz9SPf1e7

Code Example: Observable

http://plnkr.co/edit/t6zDqSAjGNvSKNzIQJtR

Understanding AngularJS 2 vs AngularJS 1: Part 2

Components instead of Controllers

While Components have been around in some shape or form around the web, Angular 2 is based around these amazingly flexible elements.

Components in AngularJS 2 will entirely replace controllers. In fact, they will also replace the concept of a module. They look like a directive, but actually act like a controller.

A component is essentially an HTML element that uses Shadow DOM to encapsulate its own scope and behavior. What this really means: your component has its own variable scope. What happens in your component, stays in your component. You can however inject your components into other components or decorate them to add functionality.

Here is an example of the previous burrito example above implemented in AngularJS 2 showing a component in action:

Decorators via Annotations

Decorators are a simple design pattern that we can now use to update the values and context of a component without introducing new behavior.

Seriously, this is great. You can just apply a decorator to your directive and change its variable values without actually tearing into its guts. Change your components color from ‘Red’ to ‘Blue’ at runtime externally without hacking away at its internal functionality or exposing some getter after the fact.

Currently, this is available in the upis provided by TypeScript, but is

A Focus on Dependency Injection

AngularJS 1.x certainly used the concept of dependency injection and promoted it with the usage of services and factories. I don’t think I need to spend a lot of time stumping why and how this can make for better encapsulation and easier re-use of code.

AngularJS 2 will take this a step further and encourage you to use dependency injection with components. Write a login component and inject it into

Zones.js

Previously, we needed to let the Digest / Apply loop cycle through your variables, or use the oft-maligned scope.$apply to let your app know that something changed. ZoneJS will now be handling all of this.

Zones is able to encapsulate the entire scope of your component and is aware of when asynchronous events start and stop.

While getting away from $apply and not having to worry about your scope is great, here comes the best part: ZonesJS will speed up execution time as much as 5x compared to AngularJS 1.x code.

Here is a great talk about Zones by Brian Ford given at the 2015 ng-conf.

The bad news: Zones is only available for modern evergreen browsers. This means if you are using IE10 or below you will not get the to use this amazing toolset. Angular 2 will have fallbacks with dirty value checking and poly-fills to make sure this is all invisible for you, but you will not see the major speed increase you would get from actually using ZonesJS.

TypeScript

TypeScript is a superset of ES6 and gives us some amazing features.

AngularJS 2 will be written in TypeScript, but this doesn’t mean you have to use it. I can say that I plan on using it as I think this will be an area

Ok, this sounds great. How do I prepare to upgrade?

I won’t go too much in depth on this but there will be upgrade paths and plans if you dont want to just ‘start over’ with your existing angular app.

The Official AngularJS 1.x to 2 Upgrade Strategy Doc offers some insight on how to upgrade.

Understanding AngularJS 2 vs AngularJS 1: Part 1

As I’m sure you know if you are reading this, the AngularJS team is planning for a major version release “very soon” that will include some major paradigm shifts. A lot of the things you learned while teaching yourself AngularJS 1.x will just not be present in AngularJS 2.

AngularJS 1.x is stable and will definitely be around for a long while with long term support from the original team. But do you really want to pass up on some of those amazing features (3-5x Performance increases, the ability to use Server Side Rendering, bragging rights)? No, of course not.

Just to make sure we can explain the concepts of Angular 2, let’s briefly review the main concepts of Angular 1.

Modules & Controllers

Controllers are just Javascript objects that create scope (more on this later), setting up attributes and functions. It’s the connection point for all scopes, functions and data sources in the application. These are similar to traffic cops that direct the flow and send data back and forth between the parts of your application.

A module can be thought of as the container that holds all the different parts of your AngularJS application. These have the advantage of making your code declarative and well encapsulated.

Directives

Custom HTML elements used to enable and interact with AngularJS. This cool feature is how we instantiate your app (`ng-app`) or create custom elements that transform data and views with JS logic stored in your models and controllers.

Here is an example of a directive in AngularJS 1.3 that replaced a `<burrito />` directive with an image of a burrito:

HTML

   <div>
<burrito></burrito>
</div>

JS

var app = angular.module(‘plunker’, []);

app.controller(‘MainCtrl’, function($scope) { });

app.directive(‘burrito’, function(){
return {
restrict: ‘E’,
replace: true,
scope: true,
template: ’<img src=“[ASSET SOURCE]” />’
};
});

Scope

The Application model and context, defined by an angular element. Defined hierarchically, scopes can be passed between elements

It’s important to note that Controllers, Services and Directives all have their own nested scopes. This can get messy when you are passing around data and need to make sure you aren’t polluting your own scope.

image

 

Databinding

 

While this is a great feature, it’s incredibly slow. Every digest cycle has to check ALL of these variables and update them appropriately.

Data binding is that magic that lets you sync data between your models and your view. In a sentence: your model’s data is bound to the view and your view is bound to your model’s data.

Here is a quick example:

HTML

<fieldset
<h1>Hello {{name}}!</h1>

<fieldset>

<label>an example of databinding:</label>

<br>

<input type=“text” ng-model=“name” />

JS

var app = angular.module(‘plunker’, []);app.controller(‘MainCtrl’, function($scope) {
$scope.name = ‘World’;
});

This is that awesome thing that does that sweet ‘live’ updating of values in your forms. Most likely, this was the huge selling point when you first started learning about AngularJS and the ‘reactive’ web.


We’ll explore where these things start to differ in Angular 2 in our next post

AngularJS JSONP GET Example

AngularJS JSONP GET Example

This is an example of a cross domain GET request using JSONP, the most common way to get data. Like the previous example using CORS, this too uses requires the server to be ‘aware’ of request so it can reply with the JSONP callback method.

The “P” in the JSONP actually stands for padding, which really means “Named Function”. You pass along a named javascript function that tells the server to wrap its response and when it responds your data is neatly wrapped with a helper function. This gets around the Same Origin Policy since <script> tags are ok’d for cross domain execution, which is how we can include JS libs from CDNs and other sources.

This method does require control over the request destination, or the site itself has to support a JSONP callback. This is just a javascript function returned from a ‘black box’, so there are some serious security concerns (but you’re not sending sensitive data via GET, right?). Also, we should note that this method have VERY limited support for reporting errors. Most people work around this by timing a response check and timeouts (which someday we may blog about).

AngularJS CORS example using httpbin.org

AngularJS CORS example using httpbin.org

This is an example of a cross domain GET and POST request to a server with CORS headers enabled. It’s a very simple one field form that displays the echo’d response from httpbin. I chose httpbin since I knew it had CORS headers enabled, and seemed like a relatively simplistic tool to play around with.

As the code shows, GET requests are quite simple and look like a regular $http call. The heavy lifting is all done by the server

The POST request on the other hand is a little more complicated and requires some manipulation of the headers before the request itself.

First, we need to set the Content-Type to form-urlencoded to let the destination know we are posting form data:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

Second, we need to delete a header called “Requested-With” that is sent along with AJAX requests:

delete $http.defaults.headers.common['X-Requested-With'];

Also, to stop this mistruth from spreading any farther: A lot of blog posts about Cross Domain posting with Angular will show you this code:

$http.defaults.useXDomain = true

It’s not a real config value, you don’t need it. Seriously. Try it with and later without it, you won’t see a difference (I think the dojo toolkit may require it, I’m not sure how it made it’s way into multiple AngularJS examples).

Cross Domain AJAX & AngularJS: The Same Origin Policy

We are big fans of AngularJS here at Arroyo Labs, and often our Angular Apps require a lot of AJAX to work: a simple GET request to load data here, a form POST there. You know, typical web stuff.

More than once we’ve made an App that needs to make an AJAX request to a different domain than the one our app lives on and hit some roadblocks. For one, your browser doesn’t really allow it (I’ll explain this later) and for the most part it’s a pain compared to hitting a local resource.

“Why would you need to do that? Why aren’t you making locally hosted APIs to access this data?!” you may blurt out while reading this. Well sometimes, you have to.

Sometimes you run into a weird legacy architecture or you can’t access the backend code. You may even want to do all of this work with only front-end level code. What if you need the client’s browser to resolve a domain for you? It’s also possible you have been making AJAX requests to other domains and never encountered an issue until now.

The point is, eventually you will have to make an AJAX request on another domain, so lets talk about it.

The Same Origin Policy

The Same Origin Policy is a security feature built into your browser (and most everybody else’s) for your safety. It prevents scripts from accessing anything outside of the current ‘site’ as the executed script, and by site I mean the same Scheme + Hostname + Port as the page executing the script.

Take a look at this chart from the wikipedia page, for a script executing from http://www.example.com/dir/page.html

image

You can’t even make a request to a subdomain like http://foobar.example.com without Same Origin stepping in and waving its finger in your face. Try it, and check your console log: “not allowed by Access-Control-Allow-Origin" all over the place.

Why does this policy exist? Imagine an internet where we could access any domain’s HTML or make a POST ‘on your behalf’ (to websites you are logged into like your bank or twitter) from your browser with Javascript. Thats a scary place.

So, how do we get around the Same Origin Policy?

Theres a few ways to ‘relax’ the Same Origin Policy so you can actually interact with data from another domain.

1) CORS

Introduced relatively recently are a type of headers that tell your browser its ok with a requests from another domain. This is known as Cross Origin Resource Sharing or CORS. With these headers turned on, you can make POST & GETs just like you would with an endpoint on the same server as your script.

You will need access to the webserver configuration to make this happen, which is not an option for a site you have no control over. The guys over at enable-cors.org do a good job explaining how to enable this for the most common webservers.

Also, I should note, this is the only method that allows you to send a POST request to another domain.

In fact, here is our example

2) Proxy (with CORS)

This solution involves a middle man proxy that does have a CORS headers that passes along your request to a server that does not have CORS headers. Yes, this is a hack-y way to just make a cURL call to a webservice.

There is the hosted flavor (which is inherently unsafe, since they can see/log everything you send) or the self hosted variety.

3) JSONP

This is the most common way to make a GET request to another domain, and is probably the method with the least effort required.

The “P” in the JSONP actually stands for padding, which really means “Named Function”. You pass along a named javascript function that tells the server to wrap its response and when it responds your data is neatly wrapped with a helper function. This gets around the Same Origin Policy since <script> tags are ok’d for cross domain execution, which is how we can include JS libs from CDNs and other sources.

This method does require control over the request destination, or the site itself has to support a JSONP callback. This is just a javascript function returned from a ‘black box’, so there are some serious security concerns (but you’re not sending sensitive data via GET, right?). Also, we should note that this method have VERY limited support for reporting errors. Most people work around this by timing a response check and timeouts.

4) Cross Document Messaging

This method isn’t really possible with the $http object (the traditional way to make AJAX requests with AngularJS), but it’s still a viable option for some cross domain communication. I think it’s an interesting concept worth exploring and I think would be a cool way to explore promises and error states.

Conclusion

With some work and concessions, you can make cross domain requests. We’ll provide some working code examples soon.