如何使用PhantomJS启动Angular摘要循环?

时间:2016-03-29 21:30:30

标签: javascript jquery angularjs phantomjs

我正在使用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代码?

2 个答案:

答案 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();
});