单击具有给定类的页面上的所有锚标记,但在导航之前取消

时间:2014-07-07 05:07:33

标签: javascript casperjs

尝试自动执行某些分析跟踪代码的某些测试,当我尝试将links传递到each()方法时,我遇到了问题。

我从stackoverflow - how to follow all links in casperjs复制了很多内容,但我不需要返回链接的href;我需要返回链接本身(所以我可以点击它)。我一直得到这个error: each() only works with arrays.我没有返回数组吗?

更新

对于每个包含.myClass的锚标记,单击它,然后从casper.options.onResourceReceived返回请求的参数,例如事件类别,事件动作等。我可能会或可能不会取消点击后发生的导航;我只需要查看请求,而不需要加载后续页面。

测试步骤:

  1. 点击包含.myClass
  2. 的链接
  3. 查看请求参数
  4. 取消点击以阻止其转到下一页。
  5. 我是javascript和casper.js的新手,所以如果我误解了,我会道歉。

    另一个更新: 我已经更新了代码,而是返回一个类数组。虽然这里有一些粗略的代码(参见注释内联)。

    但是,我现在遇到点击后取消导航的问题。 .Clear()取消了所有的js。无论如何要防止点击后发生默认动作?喜欢e.preventDefault();

    var casper = require('casper').create({
        verbose: true,
        logLevel: 'debug'
    });
    
    casper.options.onResourceReceived = function(arg1, response) {
    
        if (response.url.indexOf('t=event') > -1) {
            var query = decodeURI(response.url);
            var data = query.split('&');
            var result = {};
            for (var i = 0; i < data.length; i++) {
                var item = data[i].split('=');
                result[item[0]] = item[1];
            }
            console.log('EVENT CATEGORY = ' + result.ec + '\n' +
                'EVENT ACTION = ' + result.ea + '\n' +
                'EVENT LABEL = ' + decodeURIComponent(result.el) + '\n' +
                'REQUEST STATUS = ' + response.status
            );
    
        }
    };
    
    var links;
    //var myClass = '.myClass';
    
    casper.start('http://www.leupold.com', function getLinks() {
        links = this.evaluate(function() {
    
            var links = document.querySelectorAll('.myClass');
            // having issues when I attempted to pass in myClass var.
    
            links = Array.prototype.map.call(links, function(link) {
    
                // seems like a sketchy way to get a class. what happens if there are multiple classes?
                return link.getAttribute('class');
            });
    
            return links;
        });
    });
    
    casper.waitForSelector('.myClass', function() {
    
        this.echo('selector is here');
        //this.echo(this.getCurrentUrl());
        //this.echo(JSON.stringify(links));
    
        this.each(links, function(self, link) {
            self.echo('this is a class : ' + link);
            // again this is horrible
            self.click('.' + link);
        });
    });
    
    
    
    casper.run(function() {
        this.exit();
    });
    

1 个答案:

答案 0 :(得分:4)

您需要处理两个问题。

1。根据类

选择元素

通常多次使用一个类。因此,当您首先选择基于此类的元素时,您将获得具有该类的元素,但不保证这将是唯一的。例如,请参阅.myClass选择的元素选择:

  1. myClass
  2. myClass myClass2
  3. myClass myClass3
  4. myClass
  5. myClass myClass3
  6. 当您稍后迭代这些类名时,您遇到了问题,因为永远不能使用casper.click("." + links[i].replace(" ", "."))单击4和5(您需要另外用点替换空格)。 casper.click仅点击特定选择器的第一个匹配项。这就是I used createXPathFromElement取自stijn de ryck以查找页面上下文中每个元素的唯一XPath表达式的原因。

    然后,您可以通过像此

    这样的唯一XPath单击正确的元素
    casper.click(x(xpathFromPageContext[i]));
    

    2。取消导航

    这可能取决于您的网页实际是什么。

    注意:我使用的casper.test属性是Tester module。你可以通过调用这样的casper来访问它:casperjs test script.js

    注意:还有casper.waitForResource功能。看看吧。

    2.1 Web 1.0

    当点击意味着将加载新页面时,您可以向page.resource.requested事件添加事件处理程序。然后,您可以abort() request而不将页面重置回startURL

    var resourceAborted = false;
    casper.on('page.resource.requested', function(requestData, request){
        if (requestData.url.match(/someURLMatching/)) {
            // you can also check requestData.headers which is an array of objects:
            // [{name: "header name", value: "some value"}]
            casper.test.pass("resource passed");
        } else {
            casper.test.fail("resource failed");
        }
        if (requestData.url != startURL) {
            request.abort();
        }
        resourceAborted = true;
    });
    

    并且在测试流程中:

    casper.each(links, function(self, link){
        self.thenClick(x(link));
        self.waitFor(function check(){
            return resourceAborted;
        });
        self.then(function(){
            resourceAborted = false; // reset state
        });
    });
    

    2.2单页面应用

    可能有很多事件处理程序附加,很难阻止它们。

    是一种更简单的方法(至少对我而言)
    1. 获取所有独特的元素路径,
    2. 遍历列表,每次执行以下操作:
      1. 再次打开原始页面(基本上是每个链接的重置)
      2. 点击当前的XPath
    3. 这基本上就是我在this answer中所做的。

      由于单页应用不会加载页面。不会触发navigation.requestedpage.resource.requested。如果要检查某些API调用,则需要resource.requested事件:

      var clickPassed = -1;
      casper.on('resource.requested', function(requestData, request){
          if (requestData.url.match(/someURLMatching/)) {
              // you can also check requestData.headers which is an array of objects:
              // [{name: "header name", value: "some value"}]
              clickPassed = true;
          } else {
              clickPassed = false;
          }
      });
      

      并且在测试流程中:

      casper.each(links, function(self, link){
          self.thenOpen(startURL);
          self.thenClick(x(link));
          self.waitFor(function check(){
              return clickPassed !== -1;
          }, function then(){
              casper.test.assert(clickPassed);
              clickPassed = -1;
          }, function onTimeout(){
              casper.test.fail("Resource timeout");
          });
      });