Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
step-13 REST and Custom Services
Browse files Browse the repository at this point in the history
- Replace `$http` with `$resource`.
- Create a custom `Phone` service that represents the RESTful client.
- Use a custom Jasmine equality tester in unit tests to ignore irrelevant properties.
  • Loading branch information
petebacondarwin committed Jul 7, 2016
1 parent 9307517 commit bfed542
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 23 deletions.
2 changes: 1 addition & 1 deletion app/core/core.module.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';

// Define the `core` module
angular.module('core', []);
angular.module('core', ['core.phone']);
4 changes: 4 additions & 0 deletions app/core/phone/phone.module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use strict';

// Define the `core.phone` module
angular.module('core.phone', ['ngResource']);
15 changes: 15 additions & 0 deletions app/core/phone/phone.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

angular.
module('core.phone').
factory('Phone', ['$resource',
function($resource) {
return $resource('phones/:phoneId.json', {}, {
query: {
method: 'GET',
params: {phoneId: 'phones'},
isArray: true
}
});
}
]);
43 changes: 43 additions & 0 deletions app/core/phone/phone.service.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

describe('Phone', function() {
var $httpBackend;
var Phone;
var phonesData = [
{name: 'Phone X'},
{name: 'Phone Y'},
{name: 'Phone Z'}
];

// Add a custom equality tester before each test
beforeEach(function() {
jasmine.addCustomEqualityTester(angular.equals);
});

// Load the module that contains the `Phone` service before each test
beforeEach(module('core.phone'));

// Instantiate the service and "train" `$httpBackend` before each test
beforeEach(inject(function(_$httpBackend_, _Phone_) {
$httpBackend = _$httpBackend_;
$httpBackend.expectGET('phones/phones.json').respond(phonesData);

Phone = _Phone_;
}));

// Verify that there are no outstanding expectations or requests after each test
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});

it('should fetch the phones data from `/phones/phones.json`', function() {
var phones = Phone.query();

expect(phones).toEqual([]);

$httpBackend.flush();
expect(phones).toEqual(phonesData);
});

});
3 changes: 3 additions & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="app.css" />
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="app.module.js"></script>
<script src="app.config.js"></script>
<script src="core/core.module.js"></script>
<script src="core/checkmark/checkmark.filter.js"></script>
<script src="core/phone/phone.module.js"></script>
<script src="core/phone/phone.service.js"></script>
<script src="phone-list/phone-list.module.js"></script>
<script src="phone-list/phone-list.component.js"></script>
<script src="phone-detail/phone-detail.module.js"></script>
Expand Down
12 changes: 5 additions & 7 deletions app/phone-detail/phone-detail.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@ angular.
module('phoneDetail').
component('phoneDetail', {
templateUrl: 'phone-detail/phone-detail.template.html',
controller: ['$http', '$routeParams',
function PhoneDetailController($http, $routeParams) {
controller: ['$routeParams', 'Phone',
function PhoneDetailController($routeParams, Phone) {
var self = this;
self.phone = Phone.get({phoneId: $routeParams.phoneId}, function(phone) {
self.setImage(phone.images[0]);
});

self.setImage = function setImage(imageUrl) {
self.mainImageUrl = imageUrl;
};

$http.get('phones/' + $routeParams.phoneId + '.json').then(function(response) {
self.phone = response.data;
self.setImage(self.phone.images[0]);
});
}
]
});
4 changes: 3 additions & 1 deletion app/phone-detail/phone-detail.component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ describe('phoneDetail', function() {
}));

it('should fetch the phone details', function() {
expect(ctrl.phone).toBeUndefined();
jasmine.addCustomEqualityTester(angular.equals);

expect(ctrl.phone).toEqual({});

$httpBackend.flush();
expect(ctrl.phone).toEqual(xyzPhoneData);
Expand Down
3 changes: 2 additions & 1 deletion app/phone-detail/phone-detail.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

// Define the `phoneDetail` module
angular.module('phoneDetail', [
'ngRoute'
'ngRoute',
'core.phone'
]);
14 changes: 6 additions & 8 deletions app/phone-list/phone-list.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ angular.
module('phoneList').
component('phoneList', {
templateUrl: 'phone-list/phone-list.template.html',
controller: ['$http', function PhoneListController($http) {
var self = this;
self.orderProp = 'age';

$http.get('phones/phones.json').then(function(response) {
self.phones = response.data;
});
}]
controller: ['Phone',
function PhoneListController(Phone) {
this.phones = Phone.query();
this.orderProp = 'age';
}
]
});
7 changes: 3 additions & 4 deletions app/phone-list/phone-list.component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ describe('phoneList', function() {
describe('PhoneListController', function() {
var $httpBackend, ctrl;

// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
// This allows us to inject a service and assign it to a variable with the same name
// as the service while avoiding a name conflict.
beforeEach(inject(function($componentController, _$httpBackend_) {
$httpBackend = _$httpBackend_;
$httpBackend.expectGET('phones/phones.json')
Expand All @@ -21,7 +18,9 @@ describe('phoneList', function() {
}));

it('should create a `phones` property with 2 phones fetched with `$http`', function() {
expect(ctrl.phones).toBeUndefined();
jasmine.addCustomEqualityTester(angular.equals);

expect(ctrl.phones).toEqual([]);

$httpBackend.flush();
expect(ctrl.phones).toEqual([{name: 'Nexus S'}, {name: 'Motorola DROID'}]);
Expand Down
2 changes: 1 addition & 1 deletion app/phone-list/phone-list.module.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';

// Define the `phoneList` module
angular.module('phoneList', []);
angular.module('phoneList', ['core.phone']);
1 change: 1 addition & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"dependencies": {
"angular": "1.5.x",
"angular-mocks": "1.5.x",
"angular-resource": "1.5.x",
"angular-route": "1.5.x",
"bootstrap": "3.3.x"
}
Expand Down
1 change: 1 addition & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = function(config) {

files: [
'bower_components/angular/angular.js',
'bower_components/angular-resource/angular-resource.js',
'bower_components/angular-route/angular-route.js',
'bower_components/angular-mocks/angular-mocks.js',
'**/*.module.js',
Expand Down

0 comments on commit bfed542

Please sign in to comment.