单击具有给定类别的页面上的所有锚标签,但在导航之前取消 [英] Click all anchor tags on page with given class, but cancel prior to navigation

查看:81
本文介绍了单击具有给定类别的页面上的所有锚标签,但在导航之前取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试自动化一些分析跟踪代码的测试,当我尝试将链接传递到 each()时遇到问题方法。

Trying to automate some testing for some analytics tracking code, and I'm running into issues when I try passing links into the each() method.

我从 stackoverflow复制了很多内容-如何关注其中的所有链接casperjs ,但是我不需要返回链接的 href ;我需要返回链接本身(以便可以单击它)。我不断收到此错误:each()仅适用于数组。我不返回数组吗?

I copied a lot of this from stackoverflow - how to follow all links in casperjs, but I don't need return the href of the link; I need to return the link itself (so I can click it). I keep getting this error: each() only works with arrays. Am I not returning an array?

更新:

对于每个具有.myClass的锚标签,单击它,然后从 casper.options返回所请求的参数。 onResourceReceived 例如事件类别,事件操作等。我可能会或不必取消单击之后发生的导航;我只需要检查请求,而无需加载以下页面。

For each anchor tag that has .myClass, click it, then return requested parameters from casper.options.onResourceReceived e.g. event category, event action, etc. I may or may not have to cancel the navigation the happens after the click; I simply only need to review the request, and do not need the follow page to load.

测试步骤:


  1. 单击链接为 .myClass

  2. 查看请求参数

  3. 取消点击以阻止其进入下一页。

我是javascript和casper.js的新手

I'm new to javascript and casper.js, so I apologize if I'm misinterpreting.

另一个更新:
我已经更新了代码以代替返回数组类。不过,其中有一些粗略的代码(请参见内联注释)。

ANOTHER UPDATE: I've updated the code to instead return an array of classes. There are a few sketchy bits of code in this though (see comments inline).

但是,我现在在点击后取消导航时遇到了问题。 .Clear()取消了所有js。是否要防止单击后发生默认操作?像 e.preventDefault();

However, I'm now having issues canceling the navigation after the click. .Clear() canceled all js. Anyway to prevent default action happening after click? Like 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();
});


推荐答案

您要处理两个问题。

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

Usually a class is used multiple times. So when you first select elements based on this class, you will get elements that have that class, but it is not guaranteed that this will be unique. See for example this selection of element that you may select by .myClass:


  1. myClass

  2. myClass myClass2

  3. myClass myClass3

  4. myClass

  5. myClass myClass3

  1. myClass
  2. myClass myClass2
  3. myClass myClass3
  4. myClass
  5. myClass myClass3

稍后您遍历这些类名时,您会出现了问题,因为无法使用 casper.click(。 +链接[i] .replace(,。))(您还需要用点替换空格)。 casper.click 仅单击特定选择器的首次出现。这就是为什么我使用从createXPathFromElement https://stackoverflow.com/a/5178132/1816580\">stryn de ryck 来找到页面上下文内每个元素的唯一XPath表达式。

When you later iterate over those class names, you've got a problem, because 4 and 5 can never be clicked using casper.click("." + links[i].replace(" ", ".")) (you need to additionally replace spaces with dots). casper.click only clicks the first occurrence of the specific selector. That is why I used createXPathFromElement taken from stijn de ryck to find the unique XPath expression for every element inside the page context.

然后您可以通过像这样的唯一XPath单击正确的元素

You can then click the correct element via the unique XPath like this

casper.click(x(xpathFromPageContext[i]));



2。取消导航



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

2. Cancelling navigation

This may depend on what your page actually is.

注意:我使用 casper.test 属性,即测试器模块。您可以通过调用casper这样来访问它: casperjs test script.js

Note: I use the casper.test property which is the Tester module. You get access to it by invoking casper like this: casperjs test script.js.

注意: 还有 casper。 waitForResource 函数。

Note: There is also the casper.waitForResource function. Have a look at it.

当单击表示将加载新页面时,您可以将事件处理程序添加到 page.resource.requested 事件。然后,您可以 abort() 请求,而无需将页面重新设置为 startURL

When a click means a new page will be loaded, you may add an event handler to the page.resource.requested event. You can then abort() the request without resetting the page back to the 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单页应用程序



有可能附加了如此多的事件处理程序,很难阻止所有这些事件处理程序。

2.2 Single page application

There may be so many event handlers attached, that it is quite hard to prevent them all. An easier way (at least for me) is to


  1. 获得所有唯一的元素路径,

  2. 在列表中重复并每次执行以下操作:

  1. get all the unique element paths,
  2. iterate over the list and do every time the following:

  1. 再次打开原始页面(基本上是对每个链接进行重置)

  2. 点击当前XPath


这基本上是我在此答案中这样做。

This is basically what I do in this answer.

因为单页应用没有无法加载页面。 navigation.requested page.resource.requested 不会被触发。您需要 resource.requested 事件,如果您想检查一些API调用:

Since single page apps don't load pages. The navigation.requested and page.resource.requested will not be triggered. You need the resource.requested event if you want to check some API call:

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");
    });
});

这篇关于单击具有给定类别的页面上的所有锚标签,但在导航之前取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆