问题描述
尝试自动化一些分析跟踪代码的测试,当我尝试将链接
传递到 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.
我从,但是我不需要返回链接的 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.
测试步骤:
- 单击链接为
.myClass
- 查看请求参数
- 取消点击以阻止其进入下一页。
我是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
:
-
myClass
-
myClass myClass2
-
myClass myClass3
-
myClass
-
myClass myClass3
myClass
myClass myClass2
myClass myClass3
myClass
myClass myClass3
稍后您遍历这些类名时,您会出现了问题,因为无法使用 casper.click(。 +链接[i] .replace(,。))
(您还需要用点替换空格)。 casper.click
仅单击特定选择器的首次出现。这就是为什么 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
.
注意: 还有函数。
Note: There is also the casper.waitForResource
function. Have a look at it.
当单击表示将加载新页面时,您可以将事件处理程序添加到事件。然后,您可以 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
- 获得所有唯一的元素路径,
- 在列表中重复并每次执行以下操作:
- get all the unique element paths,
- iterate over the list and do every time the following:
- 再次打开原始页面(基本上是对每个链接进行重置)
- 点击当前XPath
这基本上是我在中这样做。
This is basically what I do in this answer.
因为单页应用没有无法加载页面。 和不会被触发。您需要事件,如果您想检查一些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");
});
});
这篇关于单击具有给定类别的页面上的所有锚标签,但在导航之前取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!