我正在使用PhantomJs(虚拟浏览器)和JQuery来自动浏览网站。但我被困在登录页面 - 尝试提交用户名和密码。
这个网站是一个有角度的应用程序。我使用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>
LoginCtrl:
$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);
});
经过一些调试后我发现数据绑定是个问题。上面的代码不会触发角度摘要循环。
当jquery点击登录按钮时 - 即使填写了user.username和user.password,也会从角度透视图保持为空。 ng-model它没有做它的魔力。用户为空,控制器将空数据提交给服务器 - 这就是我获得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用于整天测试,所以普通人 - 测试角度应用程序的人 - 如何做:自动登录,注册,导航所有这些 - 他们如何开始摘要周期 - 来自放置在page.evaluate方法中的JQuery代码?
答案 0 :(得分:2)
我找到了答案。问题是我预期的角度绑定。为了在角度世界之外更新ng-model表单 - 从JQuery开始 - 你需要使用触发器(&#34;输入&#34;)事件。
ng-model基本上听取了这个&#34;输入&#34;事件 - 在内部,它将自动触发摘要循环。在键盘上键入时,也会始终发送此输入事件。 (我在这里找到了这个解释: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);
});
答案 1 :(得分:1)
没有JQuery的解决方案
page.evaluate(function() {
var emailInput = document.getElementById('emailField'),
passwordInput = document.getElementById('passwordField'),
loginButton = document.getElementById('loginButton');
emailInput.value = 'email@domain.com';
emailInput.dispatchEvent(new Event('input'));
passwordInput.value = 'mypassword';
passwordInput.dispatchEvent(new Event('input'));
loginButton.click();
});