尝试自动执行某些分析跟踪代码的某些测试,当我尝试将links
传递到each()
方法时,我遇到了问题。
我从stackoverflow - how to follow all links in casperjs复制了很多内容,但我不需要返回链接的href
;我需要返回链接本身(所以我可以点击它)。我一直得到这个error: each() only works with arrays.
我没有返回数组吗?
更新
对于每个包含.myClass的锚标记,单击它,然后从casper.options.onResourceReceived
返回请求的参数,例如事件类别,事件动作等。我可能会或可能不会取消点击后发生的导航;我只需要查看请求,而不需要加载后续页面。
测试步骤:
.myClass
我是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();
});
答案 0 :(得分:4)
您需要处理两个问题。
通常多次使用一个类。因此,当您首先选择基于此类的元素时,您将获得具有该类的元素,但不保证这将是唯一的。例如,请参阅.myClass
选择的元素选择:
myClass
myClass myClass2
myClass myClass3
myClass
myClass myClass3
当您稍后迭代这些类名时,您遇到了问题,因为永远不能使用casper.click("." + links[i].replace(" ", "."))
单击4和5(您需要另外用点替换空格)。 casper.click
仅点击特定选择器的第一个匹配项。这就是I used createXPathFromElement
取自stijn de ryck以查找页面上下文中每个元素的唯一XPath表达式的原因。
然后,您可以通过像此
这样的唯一XPath单击正确的元素casper.click(x(xpathFromPageContext[i]));
这可能取决于您的网页实际是什么。
注意:我使用的casper.test
属性是Tester module。你可以通过调用这样的casper来访问它:casperjs test script.js
。
注意:还有casper.waitForResource
功能。看看吧。
当点击意味着将加载新页面时,您可以向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
});
});
可能有很多事件处理程序附加,很难阻止它们。
是一种更简单的方法(至少对我而言)这基本上就是我在this answer中所做的。
由于单页应用不会加载页面。不会触发navigation.requested
和page.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");
});
});