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

Commit bfed542

Browse files
step-13 REST and Custom Services
- 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.
1 parent 9307517 commit bfed542

13 files changed

+88
-23
lines changed

app/core/core.module.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
'use strict';
22

33
// Define the `core` module
4-
angular.module('core', []);
4+
angular.module('core', ['core.phone']);

app/core/phone/phone.module.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
'use strict';
2+
3+
// Define the `core.phone` module
4+
angular.module('core.phone', ['ngResource']);

app/core/phone/phone.service.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
angular.
4+
module('core.phone').
5+
factory('Phone', ['$resource',
6+
function($resource) {
7+
return $resource('phones/:phoneId.json', {}, {
8+
query: {
9+
method: 'GET',
10+
params: {phoneId: 'phones'},
11+
isArray: true
12+
}
13+
});
14+
}
15+
]);

app/core/phone/phone.service.spec.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
describe('Phone', function() {
4+
var $httpBackend;
5+
var Phone;
6+
var phonesData = [
7+
{name: 'Phone X'},
8+
{name: 'Phone Y'},
9+
{name: 'Phone Z'}
10+
];
11+
12+
// Add a custom equality tester before each test
13+
beforeEach(function() {
14+
jasmine.addCustomEqualityTester(angular.equals);
15+
});
16+
17+
// Load the module that contains the `Phone` service before each test
18+
beforeEach(module('core.phone'));
19+
20+
// Instantiate the service and "train" `$httpBackend` before each test
21+
beforeEach(inject(function(_$httpBackend_, _Phone_) {
22+
$httpBackend = _$httpBackend_;
23+
$httpBackend.expectGET('phones/phones.json').respond(phonesData);
24+
25+
Phone = _Phone_;
26+
}));
27+
28+
// Verify that there are no outstanding expectations or requests after each test
29+
afterEach(function () {
30+
$httpBackend.verifyNoOutstandingExpectation();
31+
$httpBackend.verifyNoOutstandingRequest();
32+
});
33+
34+
it('should fetch the phones data from `/phones/phones.json`', function() {
35+
var phones = Phone.query();
36+
37+
expect(phones).toEqual([]);
38+
39+
$httpBackend.flush();
40+
expect(phones).toEqual(phonesData);
41+
});
42+
43+
});

app/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
77
<link rel="stylesheet" href="app.css" />
88
<script src="bower_components/angular/angular.js"></script>
9+
<script src="bower_components/angular-resource/angular-resource.js"></script>
910
<script src="bower_components/angular-route/angular-route.js"></script>
1011
<script src="app.module.js"></script>
1112
<script src="app.config.js"></script>
1213
<script src="core/core.module.js"></script>
1314
<script src="core/checkmark/checkmark.filter.js"></script>
15+
<script src="core/phone/phone.module.js"></script>
16+
<script src="core/phone/phone.service.js"></script>
1417
<script src="phone-list/phone-list.module.js"></script>
1518
<script src="phone-list/phone-list.component.js"></script>
1619
<script src="phone-detail/phone-detail.module.js"></script>

app/phone-detail/phone-detail.component.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@ angular.
55
module('phoneDetail').
66
component('phoneDetail', {
77
templateUrl: 'phone-detail/phone-detail.template.html',
8-
controller: ['$http', '$routeParams',
9-
function PhoneDetailController($http, $routeParams) {
8+
controller: ['$routeParams', 'Phone',
9+
function PhoneDetailController($routeParams, Phone) {
1010
var self = this;
11+
self.phone = Phone.get({phoneId: $routeParams.phoneId}, function(phone) {
12+
self.setImage(phone.images[0]);
13+
});
1114

1215
self.setImage = function setImage(imageUrl) {
1316
self.mainImageUrl = imageUrl;
1417
};
15-
16-
$http.get('phones/' + $routeParams.phoneId + '.json').then(function(response) {
17-
self.phone = response.data;
18-
self.setImage(self.phone.images[0]);
19-
});
2018
}
2119
]
2220
});

app/phone-detail/phone-detail.component.spec.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ describe('phoneDetail', function() {
2323
}));
2424

2525
it('should fetch the phone details', function() {
26-
expect(ctrl.phone).toBeUndefined();
26+
jasmine.addCustomEqualityTester(angular.equals);
27+
28+
expect(ctrl.phone).toEqual({});
2729

2830
$httpBackend.flush();
2931
expect(ctrl.phone).toEqual(xyzPhoneData);

app/phone-detail/phone-detail.module.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22

33
// Define the `phoneDetail` module
44
angular.module('phoneDetail', [
5-
'ngRoute'
5+
'ngRoute',
6+
'core.phone'
67
]);

app/phone-list/phone-list.component.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ angular.
55
module('phoneList').
66
component('phoneList', {
77
templateUrl: 'phone-list/phone-list.template.html',
8-
controller: ['$http', function PhoneListController($http) {
9-
var self = this;
10-
self.orderProp = 'age';
11-
12-
$http.get('phones/phones.json').then(function(response) {
13-
self.phones = response.data;
14-
});
15-
}]
8+
controller: ['Phone',
9+
function PhoneListController(Phone) {
10+
this.phones = Phone.query();
11+
this.orderProp = 'age';
12+
}
13+
]
1614
});

app/phone-list/phone-list.component.spec.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ describe('phoneList', function() {
99
describe('PhoneListController', function() {
1010
var $httpBackend, ctrl;
1111

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

2320
it('should create a `phones` property with 2 phones fetched with `$http`', function() {
24-
expect(ctrl.phones).toBeUndefined();
21+
jasmine.addCustomEqualityTester(angular.equals);
22+
23+
expect(ctrl.phones).toEqual([]);
2524

2625
$httpBackend.flush();
2726
expect(ctrl.phones).toEqual([{name: 'Nexus S'}, {name: 'Motorola DROID'}]);

app/phone-list/phone-list.module.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
'use strict';
22

33
// Define the `phoneList` module
4-
angular.module('phoneList', []);
4+
angular.module('phoneList', ['core.phone']);

bower.json

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"dependencies": {
99
"angular": "1.5.x",
1010
"angular-mocks": "1.5.x",
11+
"angular-resource": "1.5.x",
1112
"angular-route": "1.5.x",
1213
"bootstrap": "3.3.x"
1314
}

karma.conf.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module.exports = function(config) {
66

77
files: [
88
'bower_components/angular/angular.js',
9+
'bower_components/angular-resource/angular-resource.js',
910
'bower_components/angular-route/angular-route.js',
1011
'bower_components/angular-mocks/angular-mocks.js',
1112
'**/*.module.js',

0 commit comments

Comments
 (0)