运行Karma测试的角度错误:HTML5模式需要<base>标记

aco*_*ter 40 angularjs karma-runner

我有一个带有Rails后端的单页Angular应用程序.我在我的index.html文件中使用了一个标签,但是当我使用Karma运行我的前端单元测试时,我得到了这个:

$location in HTML5 mode requires a <base> tag to be present
Run Code Online (Sandbox Code Playgroud)

我在我的主.js文件中这样做:

angular.module('my.module').config( function($locationProvider, $routeProvider) {
  $locationProvider.html5Mode( true );
}
Run Code Online (Sandbox Code Playgroud)

那么,有没有什么方法可以<base>在业力实际呈现的页面中注入一个元素?或者,告诉Angular/Karma在运行单元测试时忽略此错误?

更新

这个Google Groups线程这个GitHub问题都描述了这个问题,但在这两种情况下解决方案都是简单地提升Angular的版本.我已经做到了,我甚至可以看到angular-mocks.js默认baseHref设置的行...

这是有问题的规范:

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/
Run Code Online (Sandbox Code Playgroud)

业力输出:

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)
Run Code Online (Sandbox Code Playgroud)

con*_*ode 78

您可以通过执行以下操作禁用基本标记检查:

$locationProvider.html5Mode({
  enabled: true,
  requireBase: false
});
Run Code Online (Sandbox Code Playgroud)

  • 这解决了问题,但打破了嵌套状态的功能 (3认同)

zur*_*fyx 22

您可以在index.html中指定基本标记,<head>如下所示:

<head>
  <base href="/">
  ...
</head>
Run Code Online (Sandbox Code Playgroud)

资料来源:http://www.jonahdempcy.com/2014/12/29/angularjs-error-locationnobase-location-html5-mode-requires-base-tag-present/

  • 谢谢@Jerry,我知道如何在HTML中编写一个`<base>`标签,我在实际的应用程序标记中有一个.;-)我试图在我的问题中表达,Karma实际上生成了一个不同的,更小的index.html文件(可能是为了隔离代码进行测试),而这就是我需要"注入"的一个.上面的答案提供了一个解决方案(告诉Angular忽略它的缺席)但是如果你知道一种告诉Karma/Angular生成带有基本tag_的index.html _的方法,那就更好了.谢谢! (2认同)

The*_*tor 6

If you can't or do not want to set requireBase to false, the solution - as others pointed out - is to add <base href="/"> in the header of your primary HTML file. To do this, you will need to specify custom HTML files for Karma, which you can then edit.

First find and copy node_modules/karma/static/context.html and node_modules/karma/static/debug.html to your unit test folder, and amend the headers of both.

Then in your karma.conf.js add the following two lines:

customContextFile: 'test/unit/context.html',
customDebugFile:   'test/unit/debug.html',
Run Code Online (Sandbox Code Playgroud)

Of course your path may vary.