如何在 angular config inc. 中正确使用全局变量。测试
How to properly use a global variable in angular config inc. testing
我正在尝试为一个 wordpress 网站编写一个 angular 主题,并且我正在关注 wordpress/angular 'pattern' 使用 functions.php
定义一个指向views/partials文件夹的全局变量,这样它就可以被路由引用。
在functions.php
中:
wp_localize_script( 'appJs', 'localized',
array (
'partials' => get_stylesheet_directory_uri() . '/views'
)
);
还有我的 angular 配置 class:
function AngularConfig($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: localized.partials + '/home.html',
controller: 'HomeController'
})
.when('/projects/', {
templateUrl: localized.partials + '/projects.html',
controller: 'ProjectsController'
})
.when('/contact/', {
templateUrl: localized.partials + '/contact.html',
controller: 'ContactController'
})
.otherwise({
redirectTo: '/'
});
}
export default AngularConfig;
在运行时这是可行的,因为 localized
是全局的,属性 为 partials
。但是,我的测试(karma、jasmine、phantomjs)失败了,因为全局尚未在其环境中定义。 (此外,以这种方式直接引用全局变量是令人讨厌的并且不利于整个 DI 运动等)
我(认为)我想将 `windowProvider' 注入配置 class,并从那里获取变量。像这样:
function AngularConfig($routeProvider, $locationProvider, $windowProvider) {
$locationProvider.html5Mode(true);
let partialsRoot = $windowProvider.$get().localized.partials;
$routeProvider
.when('/', {
templateUrl: partialsRoot + '/home.html',
controller: 'HomeController'
})
.when('/projects/', {
templateUrl: partialsRoot + '/projects.html',
controller: 'ProjectsController'
})
.when('/contact/', {
templateUrl: partialsRoot + '/contact.html',
controller: 'ContactController'
})
.otherwise({
redirectTo: '/'
});
}
export default AngularConfig;
但我不知道如何在测试启动模块之前修改 window
/windowProvider
。
我试过这个:
beforeEach(module(MODULE_NAME, function ($windowProvider) {
let $window = $windowProvider.$get();
$window.localized = {
partials: 'some-path/'
};
console.log("WINDOW:", $window);
}));
但是,除非我不在配置 class 中引用 .localized.partials
,否则 console.log
不会执行 - 这让我觉得模块(和配置)正在在函数实例化之前修改window
如有任何帮助或指点,我们将不胜感激。
谢谢
之所以有$window
服务,是因为可以stubbed/mocked,服务污染了就没必要拆掉真正的window
原始 $window
服务指的是 window
以及 $windowProvider.$get()
,因此它们可以与 window
.
互换使用
由于 Angular 服务是单例,注入 $window
服务的好处是它可以在整个应用程序中被模拟和使用,并引用同一个模拟对象。一般$window
可以这样mock
// module order matters
module(($provide) => {
$provide.factory('$window', () => {});
}, 'app');
当 Angular DI 被 $windowProvider.$get()
滥用时,情况并非如此。当这样调用时,它将引用不同的对象而不是模拟对象 $window
,除了调用它的函数范围之外,无法从任何地方访问该对象。
可以通过像这样模拟 $window
来修复此行为:
beforeEach(() => {
module({ $window: {} }, 'app');
...
这边
$windowProvider
在注入应用程序之前被模拟 config
块
$windowProvider.$get
和 $window
指的是同一个 {}
对象,因为该对象是在服务定义上创建的,没有包装在工厂函数中
- 每个规格重新发布
{}
对象。
但是正确的方法是使用 constant
:
app.constant('localized', window.localized);
正是为此而生。通过 DI 摆脱全局常量并在配置和 运行 阶段使用它们。它可以像任何其他服务一样被模拟
module(($provide) => {
$provide.constant('localized', {});
}, 'app');
我正在尝试为一个 wordpress 网站编写一个 angular 主题,并且我正在关注 wordpress/angular 'pattern' 使用 functions.php
定义一个指向views/partials文件夹的全局变量,这样它就可以被路由引用。
在functions.php
中:
wp_localize_script( 'appJs', 'localized',
array (
'partials' => get_stylesheet_directory_uri() . '/views'
)
);
还有我的 angular 配置 class:
function AngularConfig($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/', {
templateUrl: localized.partials + '/home.html',
controller: 'HomeController'
})
.when('/projects/', {
templateUrl: localized.partials + '/projects.html',
controller: 'ProjectsController'
})
.when('/contact/', {
templateUrl: localized.partials + '/contact.html',
controller: 'ContactController'
})
.otherwise({
redirectTo: '/'
});
}
export default AngularConfig;
在运行时这是可行的,因为 localized
是全局的,属性 为 partials
。但是,我的测试(karma、jasmine、phantomjs)失败了,因为全局尚未在其环境中定义。 (此外,以这种方式直接引用全局变量是令人讨厌的并且不利于整个 DI 运动等)
我(认为)我想将 `windowProvider' 注入配置 class,并从那里获取变量。像这样:
function AngularConfig($routeProvider, $locationProvider, $windowProvider) {
$locationProvider.html5Mode(true);
let partialsRoot = $windowProvider.$get().localized.partials;
$routeProvider
.when('/', {
templateUrl: partialsRoot + '/home.html',
controller: 'HomeController'
})
.when('/projects/', {
templateUrl: partialsRoot + '/projects.html',
controller: 'ProjectsController'
})
.when('/contact/', {
templateUrl: partialsRoot + '/contact.html',
controller: 'ContactController'
})
.otherwise({
redirectTo: '/'
});
}
export default AngularConfig;
但我不知道如何在测试启动模块之前修改 window
/windowProvider
。
我试过这个:
beforeEach(module(MODULE_NAME, function ($windowProvider) {
let $window = $windowProvider.$get();
$window.localized = {
partials: 'some-path/'
};
console.log("WINDOW:", $window);
}));
但是,除非我不在配置 class 中引用 .localized.partials
,否则 console.log
不会执行 - 这让我觉得模块(和配置)正在在函数实例化之前修改window
如有任何帮助或指点,我们将不胜感激。
谢谢
之所以有$window
服务,是因为可以stubbed/mocked,服务污染了就没必要拆掉真正的window
原始 $window
服务指的是 window
以及 $windowProvider.$get()
,因此它们可以与 window
.
由于 Angular 服务是单例,注入 $window
服务的好处是它可以在整个应用程序中被模拟和使用,并引用同一个模拟对象。一般$window
可以这样mock
// module order matters
module(($provide) => {
$provide.factory('$window', () => {});
}, 'app');
当 Angular DI 被 $windowProvider.$get()
滥用时,情况并非如此。当这样调用时,它将引用不同的对象而不是模拟对象 $window
,除了调用它的函数范围之外,无法从任何地方访问该对象。
可以通过像这样模拟 $window
来修复此行为:
beforeEach(() => {
module({ $window: {} }, 'app');
...
这边
$windowProvider
在注入应用程序之前被模拟config
块$windowProvider.$get
和$window
指的是同一个{}
对象,因为该对象是在服务定义上创建的,没有包装在工厂函数中- 每个规格重新发布
{}
对象。
但是正确的方法是使用 constant
:
app.constant('localized', window.localized);
正是为此而生。通过 DI 摆脱全局常量并在配置和 运行 阶段使用它们。它可以像任何其他服务一样被模拟
module(($provide) => {
$provide.constant('localized', {});
}, 'app');