我正在使用 PhantomJs(虚拟浏览器)和 JQuery 来自动浏览网站。但我停留在登录页面 - 正在尝试提交用户名和密码。
这个网站是一个 Angular 应用程序。我使用 ng-click 调用 login() 函数 - 它获取用户对象。
HTML:
<form>
<label>Username:</label>
<input type="text", ng-model="user.username" ><br>
<label>Password:</label>
<input type="text", ng-model="user.password" >
<input type="button", ng-click="login(user)" value="Login">
</form>
登录控制:
$scope.login = function(user){
var route = Restangular.all("/auth/login");
route.post(user)
.then(function(response){
console.log(response);
$window.localStorage.token = response.token;
$state.go('level1');
}, function(err){
console.log("ERROR in Logging in!");
});
};
当我从普通浏览器使用该应用程序时 - 通过在键盘上键入 - 登录功能有效。但是当我使用 PhantomJs 和 Jquery 来自动化登录过程时,却不是。
PhantomJs 像任何其他浏览器一样呈现页面 - 并使用 page.evaluate 方法和以下代码填充用户名 (123) 和密码 (123),然后单击登录按钮。这理论上应该登录用户。但实际上并非如此。
page.evaluate(function() {
$("form").find('input').eq(0).val("123"); // fill username
$("form").find('input').eq(1).val("123"); // fill password
setTimeout(function(){
$("form").find('input').eq(2).click(); // click the Login Button.
},100);
});
经过少量调试后,我认为数据绑定(bind)是问题所在。上面的代码不会触发 Angular 摘要循环。
当 jquery 单击登录按钮时 - user.username 和 user.password 即使已填充,从 Angular Angular 来看仍然为空。 ng-model 它不是在做它的魔法。用户为空, Controller 向服务器提交空数据 - 这就是我收到 401 Unauthorized 的原因!
我试过用这个:
page.evaluate(function() {
$("form").find('input').eq(0).val("123"); // fill username
$("form").find('input').eq(1).val("123"); // fill password
// trying to start an angular digest cycle
$myscope = angular.element(document.querySelector("body")).scope();
$myscope.$apply();
setTimeout(function(){
$("form").find('input').eq(2).click();
},100);
});
基本上什么都没发生。我在这里做错了什么? 我也认为这不是一个模糊的问题。 PhantomJs 整天都用于单元测试,所以普通人(测试 Angular 应用程序)是如何做的:自动登录、注册、导航所有这些——他们如何从放置在 page.evaluate 方法中的 JQuery 代码中开始摘要循环?
最佳答案
我找到了答案。正如我所料,问题是 Angular 绑定(bind)。为了更新 Angular 世界之外的 ng-model 表单 - 例如 JQuery - 你需要使用 trigger("input") 事件。
ng-model 基本上监听这个“输入”事件 - 在内部这将自动触发摘要循环。在键盘上打字时,也会一直发送此输入事件。 (我在这里找到了这个解释:How does AngularJS internally catch events like 'onclick', 'onchange'?)
解决方法:
page.evaluate(function() {
$("form").find('input').eq(0).val("123").trigger("input"); // fill username and update the ng-model
$("form").find('input').eq(1).val("123").trigger("input"); // fill username and update the ng-model
setTimeout(function(){
$("form").find('input').eq(2).click(); // click on Login button -> this is picked up normally by angular.
},100);
});
关于javascript - 如何使用 PhantomJS 启动 Angular 摘要循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36295456/