У меня есть приложение для закладок, которое принимает URL-адрес и автоматически извлекает сводку. Когда клиент запрашивает у сервера добавление новой закладки, сервер возвращает некоторую исходную информацию и инициирует процесс извлечения сводки.
В интерфейсе angular я создал директивы для добавления закладки и управления каждым элементом в списке закладок. В директиве listitem есть метод checkSummary()
, который будет опрашивать сервер для получения сводки.
У меня проблемы с модульным тестом для этой последней директивы. Он терпит неудачу с «Неудовлетворенным запросом», но когда я вхожу в консоль в разных точках, кажется, что запрос $http.get()
срабатывает, и я вижу, что переменные $scope обновляются, поэтому я действительно не понимаю, почему это может привести к сбою по этой причине. Я проверил ответы на множество разных вопросов, но не могу найти ничего, что могло бы дать некоторое представление.
Код следующий:
bookmarks.js:
angular.module( 'userpages.bookmarks', [
'ui.router',
'ui.bootstrap',
'ui.validate'
])
.config(function config( $stateProvider ) {
$stateProvider.state( 'userpages.bookmarks', {
url: '/bookmarks',
templateUrl: 'userpages/bookmarks/bookmarks.tpl.html',
controller: 'BookmarksController',
data: { pageTitle: 'Bookmarks' },
});
})
.factory('bookmarksApiResource', ['$http', function ($http) {
var bookmarksUrl = '/api/v1/bookmarks/';
var api = {
getList: function() {
return $http.get( bookmarksUrl )
.then( function(response) { return response.data; });
},
getById: function(id) {
return $http.get( bookmarksUrl + id + '/' )
.then( function(response) { return response.data; });
},
addBookmark: function(articleUrl) {
return $http.post( bookmarksUrl, {article_url: articleUrl})
.then( function(response) { return response.data; });
},
checkSummary: function(id) {
return $http.get( bookmarksUrl + id + '/?fields=summary' )
.then( function(response) { return response.data; });
}
};
return api;
}])
.controller( 'BookmarksController', ['$scope', '$stateParams', 'bookmarksApiResource',
function BookmarksController( $scope, $stateParams, bookmarksApiResource) {
$scope.username = $stateParams.username;
$scope.templates = {
bookmarks: {
toolbar: 'userpages/bookmarks/bookmarks-toolbar.tpl.html',
listitem: 'userpages/bookmarks/bookmarks-listitem.tpl.html',
}
};
$scope.addBookmarkFormCollapsed = true;
$scope.bookmarks = [];
bookmarksApiResource.getList().then( function(data) {
$scope.bookmarks = data;
});
}])
.directive('newBookmark', ['bookmarksApiResource', function(bookmarksApiResource) {
var newBookmark = {
restrict: 'E',
templateUrl: 'userpages/bookmarks/bookmarks-add-form.tpl.html',
replace: true,
link: function($scope, $element, $attrs, $controller) {
$scope.addBookmark = function(articleUrl) {
var newBookmark = bookmarksApiResource.addBookmark(articleUrl);
$scope.bookmarks.push(newBookmark);
};
}
};
return newBookmark;
}])
.directive('bookmarksListitem', ['bookmarksApiResource', '$timeout',
function(bookmarksApiResource, $timeout) {
var listitem = {
restrict: 'E',
templateUrl: 'userpages/bookmarks/bookmarks-listitem.tpl.html',
replace: true,
scope: true,
link: function($scope, $element, $attrs, $controller) {
var checkSummary = function() {
if (!$scope.bookmark.summary_extraction_done) {
bookmarksApiResource.checkSummary($scope.bookmark.id).then(function(data){
if (data.summary_extraction_done) {
$scope.bookmark.summary_extraction_done = data.summary_extraction_done;
$scope.bookmark.summary = data.summary;
} else {
$timeout(checkSummary, 1000);
}
});
}
checkSummary();
}
};
return listitem;
}])
;
а тест такой:
bookmarks.spec.js
describe( 'userpages.bookmarks', function() {
var $rootScope, $location, $compile, $controller, $httpBackend;
var $scope, elem;
beforeEach( module( 'userpages.bookmarks', 'ui.router' ) );
... other tests ...
describe('bookmarks-listitem', function() {
var testBookmark;
beforeEach(module('userpages/bookmarks/bookmarks-listitem.tpl.html'));
beforeEach(inject(function(_$rootScope_, _$compile_, _$httpBackend_){
$rootScope = _$rootScope_;
$compile = _$compile_;
$httpBackend = _$httpBackend_;
testBookmark = {
id: 1,
title: 'Title of our first article',
url: 'http://www.example.com/some/article',
summary_extraction_done: false,
summary: '',
};
}));
it('when summary_extraction_done = false, checkSummary() should call the server and update the summary with the response', function () {
$httpBackend.when('GET', '/api/v1/bookmarks/1/?fields=summary').respond(200, {
summary_extraction_done: true,
summary: 'This is the summary for article 1.'
});
$httpBackend.expect('GET', '/api/v1/bookmarks/1/?field=summary');
$scope = $rootScope.$new();
$scope.bookmark = testBookmark;
elem = $compile('<bookmarks-listitem></bookmarks-listitem>')($scope);
$scope.$digest();
$httpBackend.flush();
expect($scope.bookmark.summary_extraction_done).toBe(true);
expect($scope.bookmark.summary).toBe('This is the summary for article 1.');
});
});
});
И результаты теста таковы:
Firefox 27.0.0 (Mac OS X 10.9) userpages.bookmarks bookmarks-listitem when summary_extraction_done = false, checkSummary() should call the server and update the summary with the respone FAILED
Error: Unsatisfied requests: GET /api/v1/bookmarks/1/?field=summary in .../frontend/vendor/angular-mocks/angular-mocks.js (line 1486)
createHttpBackendMock/$httpBackend.verifyNoOutstandingExpectation@.../frontend/vendor/angular-mocks/angular-mocks.js:1486
createHttpBackendMock/$httpBackend.flush@.../frontend/vendor/angular-mocks/angular-mocks.js:1464
@.../frontend/src/app/userpages/bookmarks/bookmarks.spec.js:6
Любые предложения были бы полезны.