Running this command generates three files: a component JavaScript file, a template, and a test file.
To help think through what we want our component to do, we'll implement a test first.

In this case, we plan on having our Google Maps service handle map display.
Our component's job will be to take the results from the map service (which is a map element) and append it to an element in the component template.

To limit the test to validating just this behavior, we'll take advantage of the registration API to provide a stub maps service.
A stub stands in place of the real object in your application and simulates its behavior.
In the stub service, define a method that will fetch the map based on location, called getMapElement.

In the beforeEach function that runs before each test, we use the implicit function this.register to register our stub service in place of the maps service.
Registration makes an object available to your Ember application for things like loading components from templates and injecting services in this case.

The call to the function this.inject.service injects the service we just registered into the context of the tests, so each test may access it through this.get('mapsService').
In the example we assert that calledWithLocation in our stub is set to the location we passed to the component.

To get the test to pass, add the container element to the component template.

<div class="map-container"></div>

Then update the component to append the map output to its inner container element.
We'll add a maps service injection, and call the getMapElement function with the provided location.

We then append the map element we get back from the service by implementing didInsertElement,
which is a component lifecycle hook.
This function gets executed at render time after the component's markup gets inserted into the DOM.

Note that the test uses a dummy object as the returned map element. This can be any object because it is only used to assert that the cache has been accessed.
Also note that the location has been camelized in the cache object, so that it may be used as a key.

Now implement the service as follows. Note that we check if a map already exists for the given location and use that one, otherwise we call a Google Maps utility to create one.
We abstract our interaction with the maps API behind an Ember utility so that we can test our service without making network requests to Google.

Making Google Maps Available

Before implementing the map utility, we need to make the 3rd party map API available to our Ember app.
There are several ways to include 3rd party libraries in Ember. See the guides section on managing dependencies as a starting point when you need to add one.

Since Google provides its map API as a remote script, we'll use curl to download it into our project's vendor directory.

From your project's root directory, run the following command to put the Google maps script in your projects vendor folder as gmaps.js.
Curl is a UNIX command, so if you are on windows you should take advantage of Windows bash support, or use an alternate method to download the script into the vendor directory.

Once in the vendor directory, the script can be built into the app.
We just need to tell Ember CLI to import it using our build file:

/*jshint node:true*/
/* global require, module */
let EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
// Add options here
});
// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.
app.import('vendor/gmaps.js');
return app.toTree();
};

Accessing the Google Maps API

Now that we have the maps API available to the application, we can create our map utility.
Utility files can be generated using Ember CLI.

ember g util google-maps

The CLI generate util command will create a utility file and a unit test.
We'll delete the unit test since we don't want to test Google code.
Our app needs a single function, createMap, which makes use of google.maps.Map to create our map element, google.maps.Geocoder to lookup the coordinates of our location, and google.maps.Marker to pin our map based on the resolved location.

After we restart the server we should now see some end to end maps functionality show up on our front page!

Stubbing Services in Acceptance Tests

Finally, we want to update our acceptance tests to account for our new service.
While it would be great to verify that a map is displaying, we don't want to hammer the Google Maps API every time we run our acceptance test.
For this tutorial we'll rely on our component integration tests to ensure that the map DOM is being attached to our screen.
To avoid hitting our Maps request limit, we'll stub out our Maps service in our acceptance tests.

Often, services connect to third party APIs that are not desirable to include in automated tests.
To stub these services we simply have to register a stub service that implements the same API, but does not have the dependencies that are problematic for the test suite.

What's happening here is we are adding our own stub maps service that simply creates an empty div.
Then we are putting it in Ember's registry, and injecting it into the location-map component that uses it.
That way every time that component is created, our stub map service gets injected over the Google maps service.
Now when we run our acceptance tests, you'll notice that maps do not get rendered as the test runs.