我很难尝试在Angularjs中测试基于promise的代码.
我的控制器中有以下代码:
$scope.markAsDone = function(taskId) {
tasksService.removeAndGetNext(taskId).then(function(nextTask) {
goTo(nextTask);
})
};
function goTo(nextTask) {
$location.path(...);
}
Run Code Online (Sandbox Code Playgroud)
我想对以下情况进行单元测试:
markAsDone叫它应该打电话tasksService.removeAndGetNexttasksService.removeAndGetNext完成它应该改变位置(调用goTo)在我看来,没有简单的方法来分别测试这两个案例.
我测试第一个测试的是:
var noopPromise= {then: function() {}}
spyOn(tasksService, 'removeAndGetNext').andReturn(noopPromise);
Run Code Online (Sandbox Code Playgroud)
现在要测试第二种情况,我需要创建另一个永远的假承诺resolved.这一切都非常乏味,而且它是很多样板代码.
有没有其他方法来测试这样的东西?或者我的设计闻到了什么?
我有两个第三方模块,都定义了一个同名的工厂.显然,如果不诉诸于kludge,我无法控制这些模块的命名.
另外,我还有两个内部模块,每个模块使用两个第三方模块中的不同模块作为依赖项(如下所示).我确信我无法从当前模块的依赖项中未列出的模块访问组件,但事实证明我错了.
在这里,即使own1依赖于thirdParty1(已hello定义为hello world)它在控制器中获取hi there(来自thirdParty2).其他模块的配对也是如此.
有没有办法"隔离"模块,所以我只能使用我明确依赖的东西?如果没有,如果我可以随时达到任何目的,那么拥有模块有什么意义(假设主应用程序模块将其作为依赖项)?此外,如果我有两个模块组件命名hello,我怎么知道将使用哪个?
这是jsbin的http://jsbin.com/vapuye/3/edit?html,js,output
angular.module('app', ['own1', 'own2']);
//third-party modules
angular.module('thirdParty1', []).factory('hello', function () {
return 'hello world';
});
angular.module('thirdParty2', []).factory('hello', function () {
return 'hi there';
});
// "own" modules
angular.module('own1', ['thirdParty1']).controller('Own1Ctrl', function(hello) {
this.greet = hello;
});
angular.module('own2', ['thirdParty2']).controller('Own2Ctrl', function(hello) {
this.greet = hello;
});
Run Code Online (Sandbox Code Playgroud)
结果如下:
<body ng-app="app">
<div ng-controller="Own1Ctrl as own1">
Own1: {{ own1.greet …Run Code Online (Sandbox Code Playgroud) 我正在查看步骤列表.可以在"视图"屏幕内"查看"和"删除"每个步骤.我的StepDetails组件通过steps简单地从商店的一部分获取相应的步骤来绑定到redux商店steps.find(...):
const mapStateToProps = (state, ownProps) => {
let stepId = ownProps.params.stepId;
let step = state.steps.find(s => s.id === stepId);
return {step};
};
Run Code Online (Sandbox Code Playgroud)
现在,当(在"详细信息"中)我点击"删除步骤"时,我希望从商店中删除此步骤,并且我想导航到列表视图.
在删除时调用redux操作,返回新的步骤列表而不删除此步骤,然后调用重定向:
const deleteStep = (stepId) => {
return dispatch => {
return stepsApi.deleteStep(stepId).then(steps => {
dispatch(action(STEPS_LIST_CHANGED, {steps}));
// react-router-redux action to redirect
dispatch(redirectToList());
})
}
};
Run Code Online (Sandbox Code Playgroud)
这很好,做了我想要的,但有一个缺点:当STEPS_LIST_CHANGED调用action并从列表中删除step时,我的组件mapStateToProps在此重定向之前被调用.结果是mapStateToProps不能再明显找到这一步了,我的组件给了我错误,步骤是未定义的等等.
我能做的是检查提供给组件的步骤是否已定义,如果没有提供任何内容等等.但它是一种我不喜欢的防御性编程风格,因为我不希望我的组件知道该怎么做它得到错误的数据.
我还可以交换操作调度顺序:首先重定向然后改变状态,但是它也感觉不对(逻辑上你首先要删除然后重定向).
你如何处理这种情况?
编辑:
我最终得到的是将这个null/undefined-check放入容器组件(一个做redux接线的组件).通过这种方法,我不会用不必要的逻辑来混淆我的表达组件.它也可以被抽象出更高阶的组件(或者可能是ES7装饰器)来渲染null或者<div></div>当一些必需的道具不存在时.
我尝试在现有的 ruby 运行时中使用 RSpec,并在每次文件更改时运行规范。这是因为 JRuby 和 JVM 启动时间。为了在每次运行时消除这个问题,我想启动 ruby 一次,然后只重新加载更改的文件并运行规范。我正在使用guard(具有不同的扩展)和watchr,但似乎都遇到了下面描述的问题。
我将问题归结为 RSpec 本身。问题是,当通过RSpec::Core::Runner.run多次运行 RSpec 时,它可以正常工作,直到使用load. 然后 RSpecs 开始运行规范两次。我创建了示例项目来实时显示此问题:https ://github.com/mostr/rspec_double_run_issue
以下是示例输出:
ruby run_spec_in_loop.rb
Running spec from within ruby runtime
.
Finished in 0.00047 seconds
1 example, 0 failures
loading spec file via 'load' as if it was changed and we wanted changes to be picked up
Running spec from within ruby runtime
..
Finished in 0.001 seconds
2 examples, 0 failures
Run Code Online (Sandbox Code Playgroud)
当从现有的 ruby 运行时运行时,有什么方法可以告诉 RSpec 在后续运行之间清除其上下文吗?我还将此作为 …
在我的应用程序用户登录时,我有authService设置内部标志isAuthenticated.现在每次路线改变我都有听众附加到$routeChangeStart检查的事件authService.isAuthenticated().如果没有,它应该重定向到登录路由.
问题是用户刷新页面(所有authService设置都丢失)并再次返回登录(同时仍然在服务器上有有效的会话).这不是我想要的.
我想做的是"阻止"路由更改,直到我获得信息,如果用户已经过身份验证(无论authService是立即验证还是来自服务器,如果没有可用的信息authService,例如刷新后).我有这样的功能authService
// returns promise
currentUser: function() {
if (authService.isAuthenticated()) {
return $q.when(authService.loggedUser);
}
return $http.get('/session').then(function(response) {
authService.loggedUser = response.user;
return $q.when(authService.loggedUser);
});
}
Run Code Online (Sandbox Code Playgroud)
并希望在事件监听器中使用它.
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if(isRouteRestricted(next)) {
authService.currentUser().then(null, function() {
$location.path('/login');
});
}
});
Run Code Online (Sandbox Code Playgroud)
问题是它没有按预期工作.我仍然可以在很短的时间内看到目标路线,然后用户被重定向.我相信这是由于承诺的性质,但如何摆脱这种"眨眼"效应?
我有跨多个文件的对象定义,我使用以下语法向命名空间添加更多属性
var app = app || {};
// and then
app.namespace = {
...
}
Run Code Online (Sandbox Code Playgroud)
但JSHint警告我:
[L1:C5] W079: Redefinition of 'app'.
var app = app || {};
Run Code Online (Sandbox Code Playgroud)
我不确定这是不是真的错了,因为我已经看过它多次使用,例如与模块模式一起使用.
如果没关系,我怎么能在全球范围内压制这个警告?我找到了一种方法来抑制给定文件的给定选项
/* jshint: -W079 */
Run Code Online (Sandbox Code Playgroud)
但有没有办法在全球范围内做到这一点?或者它被认为是不好的做法?
我正在尝试将CommonChunkPlugin与一个仅包含webpack运行时的"额外"块一起使用以获得正确的散列(当仅应用程序文件发生更改时,这不会更改供应商散列).诀窍是在官方的WebPack回购描述这里.
这本身工作正常,块哈希是正确的,但问题是我生成的HTML文件包含错误的顺序:清单,应用程序,然后是供应商*,而它应该是清单,供应商,应用程序.
CommonsChunkPLugin配置如下:
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
Run Code Online (Sandbox Code Playgroud)
和条目如下:
entry: {
app: './index.js',
vendor: ['foo', 'bar', 'baz']
}
Run Code Online (Sandbox Code Playgroud)
有小费吗?
在我的node.js应用程序中,每当我收到请求时,我都想用一些唯一的ID“标记”它,并能够通过该ID跟踪与该请求相关的所有活动(日志语句)。因此,当请求传入并且我将其处理传递给较低的应用程序层(服务、数据库调用等)时,我希望能够收集与给定请求 ID 匹配的所有日志,以重建其通过应用程序的旅程。
有了这张图片,我现在使用request-local模块,但它做了一些让我失败的重大魔法(来自多个请求的日志获得相同的 ID)。
该代码主要基于 Promises(不是普通的旧节点回调),并且我使用高阶函数来提供对我的实际函数的依赖项(在启动期间构建应用程序树)。
第一个也是非常明显的解决方案是将这个请求 ID 传递给每个调用的函数,但这是一场灾难,我不会这样做。
您如何(可靠地)进行这种请求跟踪,而不显式将此 id/上下文作为额外参数传递给所有级别的函数?
我熟悉IonicFramework并构建非常简单的应用程序.现在它有一个按钮显示面板(淡入,正在尝试从底部滑入).它在Androids上工作正常,但在iOS动画开头有奇怪的闪烁(在模拟器和设备上).
基本上我的观点如下:
<ion-content class="has-header" ng-controller="MainCtrl">
<div class="container">
<button class="btn btn__big centered primary" ng-click="toggleDetails()">toggle info</button>
</div>
<div class="panel panel-animated primary ng-hide" ng-show="detailsVisible">
Details here
</div>
</ion-content>
Run Code Online (Sandbox Code Playgroud)
带动画的css类我适用于ng-show
.panel {
position: absolute;
width: 100%;
height: 40%;
top: 60%;
padding: 1em;
}
.panel-animated {
-webkit-animation: fadeIn 0.5s;
-moz-animation: fadeIn 0.5s;
animation: fadeIn 0.5s;
}
.panel-animated.ng-hide {
-webkit-animation: fadeOut 0.5s;
-moz-animation: fadeOut 0.5s;
animation: fadeOut 0.5s;
}
Run Code Online (Sandbox Code Playgroud)
我没有使用任何外部库来制作动画,只是简单的Ionic内置动画类.我使用完整的,准备好运行的应用程序创建了存储库,因此您可能需要检查它.
此外,视频显示闪烁但闪存视频是垃圾,只有一个录制,而其中有更多的实际视频在这里
我有相对简单的webpack配置文件(如下):
module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js"
},
devtool: "eval",
module: {
loaders: [
{
test: /\.css$/, loader: "style!css",
exclude: /node_modules/,
},
{
test : /.js$/,
loader : 'babel-loader' ,
exclude: /node_modules/
}
]
}
};
Run Code Online (Sandbox Code Playgroud)
我正在使用webpack-dev-server以下命令在开发中使用应用程序webpack-dev-server --inline --hot --port 9090 --content-base public/ --watch.
我读到eval在开发时建议使用源地图,但它对我不起作用.我在我的devtools中获得的内容如下.它正确显示文件(main.js和hello.js)但它包含babel-transiled内容,而不是原始内容.当我把它设置为eval-source-map它工作正常.
我的设置有什么问题?此处提供了此问题的完整项目