Reputation: 2495
If I add the flush()
call it gives me "Error: Unexpected request: GET templates/createAccountWithAcme.html". Why on earth is it telling me about a view template and how can I avoid this? This is an Ionic Framework (v 1.0.0 RC2 – AngularJS) project.
EDIT: Previously, I mistakenly omitted the $httpBackend.when or $httpBackend.whenGET call which I've tried. Same error with updated code:
EDIT 2: More details: This is an Ionic Framework project, (v1.0.0 RC2) which uses ui-router. When I tried removing all other tests, I still got the error but noticed the template it complained about was the last one defined in the UI router config (In Ionic the router is $stateProvider
). If I added a dummy state to the end of the state definitions it then became THAT one that the test complained about. So I decided the router must be trying to load in the templates which my test wasn't expecting. I've posted a fix.
describe('foo', function() {
var $http, $httpBackend;
$http = void 0;
$httpBackend = void 0;
$http = null;
$httpBackend = null;
beforeEach(module('acme'));
beforeEach(inject(function($injector) {
$http = $injector.get('$http');
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('http://www.google.com').respond({});
}));
it('should have parsed genres', function() {
console.log('foo');
$http({
method: 'GET',
url: 'http://www.google.com'
}).then(function(response) {
console.log('success: ', response);
}, function(error) {
console.log(error);
});
$httpBackend.flush();
});
});
Upvotes: 2
Views: 3841
Reputation: 8062
I have seen similar issues with unexpected get requests for HTML when unit testing directives that include other directives in their templates.
The general solution I/we employed was to add some build steps that 'compile' (sort of) all of the project's HTML templates into a single JS file, and then include that JS file in the list of javascript included in karma.conf.js. Now, when the directive loads and makes a request to the template cache for the template, the template will already be loaded (because your JS was included via karma.conf.js), and then no unexpected GET request!
Note also this is generally a good thing to do as part of your build process so your client browsers are not making N extra HTTP requests for HTML templates.
If you are on a node.js based project, you can use ng-htmljs
to convert all templates to js. Their docs explain the problem a little better as well : https://www.npmjs.com/package/ng-html2js. This is also conveniently wrapped by grunt - https://www.npmjs.com/package/grunt-html2js, and by gulp - https://www.npmjs.com/package/gulp-ng-html2js.
The node.js grunt solution in more detail:
GruntFile.coffee:
grunt.initConfig
html2js:
test:
src: ['all/my/html_templates/**/*.html']
dest: 'app/.tmp/templates.js'
options:
base : 'app/'
module: 'myAppTemplates'
singleModule: true
htmlmin:
collapseWhitespace: false
collapseBooleanAttributes: true
removeCommentsFromCDATA: true
removeOptionalTags: true
grunt.registerTask 'test', [
...
'html2js:test'
'karma:unit'
...
]
And in Karma.conf.js:
files: [
...
'app/.tmp/templates.js'
],
And don't forget in your test to include your template module:
beforeEach module 'myAppTemplates'
#or if you are using browserify:
beforeEach window.angular.mock.module 'myAppTemplates'
Upvotes: 1
Reputation: 2495
I ended up whitelisting all the html templates:
beforeEach ...
//this line solves it
$httpBackend.whenGET(/templates/.*/).respond(200, '');
$httpBackend.whenGET('http://www.google.com').respond({});
...
Upvotes: 3
Reputation: 1885
What you have to do is mock your request in your beforeEach
clause:
beforeEach(inject(function($injector) {
$http = $injector.get('$http');
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGet('http://www.google.com')
.respond('Some return');
}));
And when you execute .flush()
the promise of the get method will be solved
Upvotes: 0