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

标签 javascript jquery angularjs phantomjs

我正在使用 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/

相关文章:

php - 如何将值插入MySQL表的特定空白列?

javascript - 为什么在 angularjs 中找不到所需指令的 Controller ?

android - 制作我的 Ionic AngularJS 程序的 iOS 应用程序

Javascript 迭代 python 字典

javascript - Business Catalyst - 如何从架构元内容中删除井号

jQuery 日期选择器在与其他表单元素重叠时不起作用

javascript - 通过多个名称查找元素 jQuery

javascript - 移除与节流功能结合使用的 Scroll 事件监听器

javascript - 从 URL 获取动态查询字符串参数 - AngularJS

jquery - 使用 jQuery AJAX 调用后 JSON 数据消失