Can't retrieve href url attribute - puppeteer

I can't return the href, i did check all pages of stackoverflow to see if there is an solution, but sadly i did try a lot of them and non work.
This is how it looks:
this is a test
when i want to copy the selector it shows me this:
#bodyblock > ul > li:nth-child(1) > h4 > a
Well when i use that selector it shows me only the text (this is a test) not the link..
i need the url of that link.
i did try something like this,
var titlesList = document.querySelectorAll('#bodyblock > ul > li:nth-child(1) ');
or this
var titlesList = document.querySelectorAll('#bodyblock > ul > li:nth-child(1) ').href;
and this
let list = await page.$$eval('#bodyblock > ul > li:nth-child(1) > h4 ', a => a.href);
console.log (list)
none returns the url, what am i doing wrong?.
regards

You will need to use the selector that gets you the a element, then get the href off of that. Guessing from the selectors you have posted above, one possible way to do that:
const url = await page.$eval('#bodyblock > ul > li:nth-child(1) > h4 > a', el => el.href);

function getHref(){
var attrHref = document.querySelector("a").getAttribute("href");
console.log(attrHref);
}
getHref();
.getAttribute("href") should return the url.
Find a fiddle of the above code here:
https://jsbin.com/lototozezu/edit?html,js,console,output

Related

Wait until page is fully loaded in BackstopJS

I've a scenario where I need to search. The problem is that I need BackstopJS to wait until an animated gif is done, and after that take screenpicture. I've tried this:
{
"label": "My_search",
"cookiePath": "backstop_data/engine_scripts/cookies.json",
"url": "https://my.test.com/test/#/search",
"referenceUrl": "https://my.stage.test.com/test/#/search",
"clickSelector": "#page-wrap > search > div > ul > li:nth-child(2) > a > span",
"delay": 15000
}
Any idea how to solve this problem?
you can add the load eventListener to your page and then log a readyEvent String for BackstopJS
window.addEventListener('load', () => {
console.log('pageLoaded');
});
in your backstop scenario use "readyEvent": "pageLoaded",

Getting DomException for DropDown while using await.Hover

While using the following events in puppeteer getting error.
I had tried with both the method using Xpath and selector, unable to find the element through the script. Whereas, same selector can be traced or can be found in dev tools > Elements tab during the snippet code execution
Method 1: Selector
await page.waitForSelector('#menu-item-\$PpyNavigation1564144649507\$ppyElements\$l1\$ppyElements\$l4 > a > span > span', {visible: true});
await page.hover('#menu-item-\$PpyNavigation1564144649507\$ppyElements\$l1\$ppyElements\$l4 > a > span > span');
Error message:
events.js:116 (node:24684) UnhandledPromiseRejectionWarning: Error: Evaluation failed: DOMException: Failed to execute 'querySelector' on 'Document': '#menu-item-$PpyNavigation1564144649507$ppyElements$l1$ppyElements$l4 > a > span > span' is not a valid selector.
at predicate (eval at waitForPredicatePageFunction (:2:21), :6:20)
at eval (eval at waitForPredicatePageFunction (:2:21), :25:7)
at onRaf (puppeteer_evaluation_script:56:33)
at pollRaf (puppeteer_evaluation_script:48:5)
Update the below element as below it has worked
Earlier: Not working
await page.waitForSelector('#menu-item-\$PpyNavigation1564144649507\$ppyElements\$l1\$ppyElements\$l4 > a > span > span', {visible: true});
await page.hover('#menu-item-\$PpyNavigation1564144649507\$ppyElements\$l1\$ppyElements\$l4 > a > span > span');
Updated: Working
'await page.waitForSelector('li[id="menu-item-$PpyNavigation1564144649507$ppyElements$l1$ppyElements$l4"] > a > span > span', {visible: true});
await page.hover('li[id="menu-item-$PpyNavigation1564144649507$ppyElements$l1$ppyElements$l4"] > a > span > span');
`'

Is it possible to hide all the element tag by using only 1 id name?

I'm trying to hide certain tags by using one ID element, but seem like it only hide the first tag with the ID element that I used.
DEMO : http://jsfiddle.net/mgm3j5cd/
How can i solve this issue? I wanted to hide the tag only with the ID element that I've declared. Appreciated for helps
You have this tagged as CSS, so the following CSS in your page's stylesheet will work:
#hide {
display: none;
}
Edit:
If you must only use JavaScript, you can do the following. Keep in mind that your document is already technically invalid by having multiple elements with the same ID, so this approach may not work in every browser. (I tested with Firefox 32).
Working JSFiddle: http://jsfiddle.net/88yw7LL9/2/
function hideByID(string) {
var element = document.getElementById(string); // get first matching element
var array = [];
while(element) {
array.push(element);
element.id = string + '-processed'; // change ID so next call gets the next matching element
element = document.getElementById(string);
}
for(var i = 0; i < array.length; i++) {
array[i].id = string; // revert ID to previous state
array[i].style.display="none"; // hide
}
}
hideByID('hide');
The simplest solution should be to assign 'class' attribute to certain elements you want to hide, like :
.XXXX
{
display:none;
}
Perhaps, you want to specify some elements hidden with id, like :
#id1 , #id2
{
display:none;
}
or
div#id1 , div#id2 //more accurate
{
display:none;
}
but, unfortunately, you can't hide elements you want by using one ID.

Change CSS of an linked div/id

I link to a page like page.html#id so the page is automatically focused at this id.
How do i do this in CSS that only the div with the id from the URL gets for example a yellow background?
Thanks
Use the :target pseudo selector.
http://css-tricks.com/on-target/
Get the hash value and style it using JavaScript:
if(window.location.hash) {
var hash = window.location.hash.substring(1); //the variable without hash sign.
document.getElementById(hash).style.background = "yellow";
}
Edit - didn't know about :target. That answer is better!
You could listen for the hashchange event, detect the current hash and apply a class to the corresponding element:
window.addEventListener('hashchange', function() {
// Remove .active from any currently active elements
var active = document.getElementsByClassName('active');
for(var i = 0; i < active.length; ++i) {
active[i].classList.remove('active');
}
var id = window.location.hash.substr(1);
document.getElementById(id).classList.add('active');
});
If you need to support browsers that do not support classList, there are plenty of alternatives.
JSFiddle

el Child in each function

I have a questions.
I search for a solution for these.
Wanna use el with child function.
But didn't work sofar.
If i clear the el it works but then i have all elements class last.
Mootools Script
$$('ul#portfolio li, .ce_id').each(function(el) {
if(!el.hasClass(filterVal)) {
el.fade('out').setStyle('display', 'none').addClass('hidden');
} else {
el.setStyle('display', 'block').fade('in').removeClass('hidden');
$$(el':nth-last-child((4n+4)').addClass('last');
}
Hope you guys can help me. Or its not possible to use el or VAR with :nth-last-child together?
Update: But didn't work.
else {
el.setStyle('display', 'block').fade('in').removeClass('hidden');
el.getElements(':nth-last-child(4n+4)').addClass('last');
}
Update 2:
Here the Code
So i want when i click on print that every 4 li witch not hidden and has the class witch clicked get the class last.
http://jsfiddle.net/6whd9/1/
Best reagards
I'm cutting down on the code a bit, but you cant but the el in the selector. Instead you should use el.getChildren or el.getElements. Here is an example:
$$('#parent > div').each(function(el){
el.getChildren(':nth-last-child(4n+4)').addClass('last');
});
Here is a working example: http://jsfiddle.net/ZxMUh/
Edit: It's really hard to understand from your question what works and not. However, if you try to animate you can not just fade it in. You need to hide it first.
$$('#parent div.hidden').fade('hide');
$$('#parent > div').each(function (el) {
el.removeClass('hidden').fade('in');
el.getChildren(':nth-last-child(4n+4)').addClass('last');
});
Here is the example: http://jsfiddle.net/ZxMUh/2/
Edit (After getting the fiddle): In my example I thought you where changing the nth-child in the "li". The problem is that you can't do it in your each-statement. Do it separate.
Here is fiddle when using :nth-last-child: http://jsfiddle.net/6whd9/2/
However, is't not probably going to do what you want, and it's not really possible to use the :nth-child in this case. You have to make the selection by your self.
var visable = $$('ul#portfolio li:not(.hidden)').reverse();
visable.each(function (item, index) {
// same as 4n + 4
if (index % 4 == 3) {
item.addClass('last');
}
});
Here is a fiddle demonstrating it: http://jsfiddle.net/6whd9/4/
(I added the last class to the style with a solid red border so it would be visable)
I hope I finally understood your question...