Angular error running Karma tests: HTML5 mode requires a <base> tag

acobster picture acobster · Dec 5, 2014 · Viewed 26.9k times · Source

I have a single-page Angular app with a Rails backend. I am using a tag in my index.html file, but when I run my front-end unit tests using Karma, I get this:

$location in HTML5 mode requires a <base> tag to be present

I am doing this in my main .js file:

angular.module('my.module').config( function($locationProvider, $routeProvider) {
  $locationProvider.html5Mode( true );
}

So, is there any way I can inject a <base> element in the page that karma actually renders? Or else, tell Angular/Karma to ignore this error when running unit tests?

Update

This Google Groups thread and this GitHub issue both describe this problem but in both cases the solution is to simply bump up the version of Angular. I've done that and I can even see the line in angular-mocks.js where the default baseHref gets set...

Here is the spec in question:

describe 'amnResource', ->
  $compile = null
  $rootScope = null

  beforeEach ->
    module 'ngMock'
    module 'amn'
    module 'directive.template.cache'

    inject([ '$compile', '$rootScope', ($c, $r) ->
      $compile = $c
      $rootScope = $r
    ])

  it 'compiles to an article', ->
    console.log $rootScope
    console.log $rootScope.foo
    $rootScope.foo =
      title: 'Foo'
      excerpt: 'foo bar qux'

    element = $compile('<amn-resource resource="foo"></amn-resource>')($rootScope)
    console.log element.html()
    console.log $rootScope.foo
    expect( element.html() ).toMatch /Foo/

Karma output:

Running "karma:unit" (karma) task
INFO [karma]: Karma v0.12.28 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 39.0.2171 (Mac OS X 10.9.5)]: Connected on socket hOvsC6ji15heHZmiHxJt with id 45528987
ERROR: 'Error: [$location:nobase] $location in HTML5 mode requires a <base> tag to be present!
http://errors.angularjs.org/1.3.5/$location/nobase
    at http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:63:12
    at $LocationProvider.$get (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:11187:15)
    at Object.invoke (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4138:17)
    at $LocationProvider.origProvider.$get (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4024:43)
    at Object.invoke (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4138:17)
    at http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:3956:37
    at getService (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4097:39)
    at Object.invoke (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4129:13)
    at http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:3956:37
    at getService (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4097:39)'
ERROR: 'Error: [$location:nobase] $location in HTML5 mode requires a <base> tag to be present!
http://errors.angularjs.org/1.3.5/$location/nobase
    at http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:63:12
    at $LocationProvider.$get (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:11187:15)
    at Object.invoke (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4138:17)
    at $LocationProvider.origProvider.$get (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4024:43)
    at Object.invoke (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4138:17)
    at http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:3956:37
    at getService (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4097:39)
    at Object.invoke (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4129:13)
    at http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:3956:37
    at getService (http://localhost:9876/base/vendor/assets/javascripts/angular/angular.js?3a16995fbea0062d6334adb9277e9776ca069fa1:4097:39)'
Chrome 39.0.2171 (Mac OS X 10.9.5) Midway: Resource performs a GET request FAILED
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
LOG: Scope{$id: 2, $$childTail: null, $$childHead: null, $$prevSibling: null, $$nextSibling: null, $$watchers: null, $parent: null, $$phase: null, $root: Scope{$id: 2, $$childTail: null, $$childHead: null, $$prevSibling: null, $$nextSibling: null, $$watchers: null, $parent: null, $$phase: null, $root: Scope{$id: ..., $$childTail: ..., $$childHead: ..., $$prevSibling: ..., $$nextSibling: ..., $$watchers: ..., $parent: ..., $$phase: ..., $root: ..., $$destroyed: ..., $$listeners: ..., $$listenerCount: ..., $$isolateBindings: ..., $$asyncQueue: ..., $$postDigestQueue: ..., $$applyAsyncQueue: ...}, $$destroyed: false, $$listeners: Object{}, $$listenerCount: Object{}, $$isolateBindings: null, $$asyncQueue: [], $$postDigestQueue: [], $$applyAsyncQueue: []}, $$destroyed: false, $$listeners: Object{}, $$listenerCount: Object{}, $$isolateBindings: null, $$asyncQueue: [], $$postDigestQueue: [], $$applyAsyncQueue: []}
LOG: undefined
LOG: ''
LOG: Object{title: 'Foo', excerpt: 'foo bar qux'}
Chrome 39.0.2171 (Mac OS X 10.9.5) amnResource compiles to an article FAILED
    Expected '' to match /Foo/.
    Error: Expected '' to match /Foo/.
        at Object.<anonymous> (/Users/acobster/Dropbox/amn/amn-0.5/spec/javascripts/unit/directives/resource_spec.js:27:35)
Chrome 39.0.2171 (Mac OS X 10.9.5): Executed 3 of 3 (2 FAILED) (5.078 secs / 5.074 secs)

Answer

connorbode picture connorbode · Feb 24, 2015

You can disable the base tag check by doing the following:

$locationProvider.html5Mode({
  enabled: true,
  requireBase: false
});