I will freely admit that with puppeteer I am struggling. I'm using bootstrap-select jquery plugin to do drop downs. Here is an example of one of Jsfiddle
http://jsfiddle.net/9xr5af00/
I have tried numerous different ways of having jest - puppeteer click the dropdown and click an element on the dropdown.
(Not sure how to put puppeteer in a jsfiddle along with an example).
All the examples for puppeteer seem to indicate that I need to use the val html tag, however the bootstrap-select only uses the option tag.
This is one of the many things that I've tried
await page.click('#client-picker')
let value = "A"
await page.select('#client-picker',value)
However putting delays in it seems puppeteer doesn't actually scroll down the list. WHich I guess is right since it's just trying to do a select on an element. How can I make puppeteer scroll the list for an entry?
It create div element and you need to click the button with data-id="client-picker", select the parent and select li a element that match with the value.
await page.evaluate(() => {
let value = "A"
let clientPicker = document.querySelector('button[data-id="client-picker"]')
clientPicker.click();
let listOption = clientPicker.parentNode.querySelectorAll('li a')
Array.from(listOption).find(item => item.textContent == value).click()
});
Related
I'm using selenium to open up an instagram page and scrolling through a list of followers. However, I'm having issues with this line of code here:
self.driver.find_element_by_xpath("/html/body/div[1]/section/nav/div[2]/div/div/div[3]/div/div[5]/span").click()
The scroll bar/button element's xpath isn't correct, and I don't know how to find the correct xpath.
Also, this was someone else's code that I'm trying to run LOL-I didn't write all the code from scratch.
Selenium Scrolling
There are multiple ways to scroll down a webpage in Selenium in order to load new information. The simplest and most effective way I have found was using the Selenium.Keys method:
from selenium.webdriver.common.keys import Keys
body = driver.find_element_by_css_selector('body')
body.click()
body.send_keys(Keys.PAGE_DOWN)
More Information
I highly recommend you go through this guide if you have not already:
https://selenium-python.readthedocs.io/getting-started.html
I would suggest 3 options here (examples are in Java):
If you know exactly element what needs to become in viewport you can use following
WebElement el = driver.findElement(By.xpath("xpath"));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].scrollIntoView()",el);
Use sendKeys method mentioned here already
WebElement el = driver.findElement(By.xpath("//body"));
el.sendKeys(Keys.PAGE_DOWN)
The most tricky option, find element which has css property 'overflow' with value that makes scroll bar to appear e.g. overflow: 'auto' and using JavaScript you will be able to know exactly scrolling point and scroll in any direction as you like
WebElement el = driver.findElement(By.xpath("xpath"));
JavascriptExecutor js = (JavascriptExecutor) driver;
int scrollAmountInPx = 10;
js.executeScript("arguments[0].scrollTo(0, arguments[0].scrollTop + " + scrollAmountInPx+ ")",el);
Try:
element=self.driver.find_element_by_xpath("/html/body/div[1]/section/nav/div[2]/div/div/div[3]/div/div[5]/span")
self.driver.execute_script("arguments[0].scrollIntoView();", element)
element.click()
I am trying to click this button but I keep failing as there is also another button with the same class name with a different aria-name or I am just clicking it wrongly.
<button aria-label="upvote" aria-pressed="false" class="voteButton _2m5vzALl8kQdr9kwIFUo5t" data-click-id="upvote"><span class="_3wVayy5JvIMI67DheMYra2 _3SUsITjKNQ7Tp0Wi2jGxIM _22nWXKAY6OzAfK5GcUqWV2 qW0l8Af61EP35WIG6vnGk _3edNsMs0PNfyQYofMNVhsG"><i class="icon icon-upvote _2Jxk822qXs4DaXwsN7yyHA _39UOLMgvssWenwbRxz_iEn"></i></span></button>
my code looks like this at the moment :
await page.waitForSelector('.voteButton._2m5vzALl8kQdr9kwIFUo5t');
await page.click('.voteButton._2m5vzALl8kQdr9kwIFUo5t');
How can I click an element specifically for aria-label or data-click-id?
You must be independent from hash names like _3wVayy5JvIMI67DheMYra2
This names will be change after rebuild
You need use for your case some fixed classes like
'button[class~="voteButton"]'
And don't forget check your selector on page in console before run puppeteer:
document.querySelector('button[class~="voteButton"]');
then you can run puppeteer:
await page.waitForSelector('button[class~="voteButton"]');
await page.click('button[class~="voteButton"]');
You might have some other problem with your use case as your script should already work as expected: clicks the first element instance with the given selector (if there is a 2nd or 3rd instance: it won't touch them).
It is possible to select elements based on their specific attributes (including aria attributes) with Attribute selectors:
await page.waitForSelector('button[aria-label="upvote"]')
await page.click('button[aria-label="upvote"]')
I'm following this tutorial about Ionic and directives and everything works fine except when I try to get the FAB element using ElementRef's nativeElement.getElementsByClassName, like this:
this.fab = this.element.nativeElement.getElementsByClassName('fab')[0]
That returns undefined. The problem is when I remove the index and print the whole HTMLCollection using console.log, it shows me a complete list with all the FAB's inside the element.
Running
console.log(this.element.nativeElement.getElementsByClassName('fab'),
this.element.nativeElement.getElementsByClassName('fab')[0]);
on ngOnInit gives the following result:
What am I doing wrong here? Every part of the code related to the problem is equal to the tutorial and it's a quite recent video...
I think the reason here is that those elements are not present while you asking for them with that line:
console.log(this.element.nativeElement.getElementsByClassName('fab'),
this.element.nativeElement.getElementsByClassName('fab')[0]);
There is simple example which shows where problem can be:
console.log(document.getElementsByClassName('fab'), document.getElementsByClassName('fab')[0]);
const el1 = document.createElement('div');
el1.setAttribute('class', 'fab');
const el2 = document.createElement('div');
el2.setAttribute('class', 'fab');
setTimeout(() => {
this.abc.nativeElement.appendChild(el1);
this.abc.nativeElement.appendChild(el2);
}, 2000);
Elements are added after 2 seconds and console log is same like yours, but when you click on HTMLCollection it will evaluate and shows you those elements - of course if you click after 2 seconds(when elements are present).
If those element are really present when you asking for them console log should look more like:
HTMLCollection(2) [div.fab, div.fab]
Also, note that this little i in Google Chrome console inform you that value is evaluted just now - at the moment when you click on it.
I'm making a page that has 4 in-page tabs on it. To link to those tabs, the URL is
URL/#tab-1-tab; URL/#tab-2-tab etc
Now, in one of the tabs I want to have buttons that link to specific points on a page inside another tab, but not sure if it's actually possible to link to.
I've made the anchors on that page with
<a name="1"></a>
But I can't figure out how to link to them. I tried
URL/#tab-4-tab/#1 and URL/#tab-4-tab#1
Not sure what else to try. The links do work if I go to the tab with the anchors, then erase the tab url bit and just put in the anchor link, so instead of
URL/#tab-4-tab, I type in URL/#1
Then it jumps to the right point.
But that doesn't work if I'm on any other tab or page.
Is it possible to do this somehow?
If your using tabs to switch div CSS properties like display:none / display:block then you will need some jQuery / JavaScript to switch them based of URL no differently then your jQuery that listens for the tabs "onclick" event then shows that relative div.
First step would be to obtain a JavaScript URL reader that listens for variables or hashtag-bookmarks. Here is an example of a variable reader I have used before.
http://jsfiddle.net/googabeast/hhkuj/
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
//usage
var myVar = getUrlVars()["tab"];
That would make the URL format slightly different then your above posting, something more like "index.php?tab=2" / "index.php?tab=3" etc...
Next phase would be generate a switch based off the incoming URL variables to properly show the requested div.
I'm sure this question is out there but I cannot find it:
Is there a tool that can get one element of my HTML document and export that element, all its parents and all its associated CSS but nothing else?
EDIT:
Sorry I was not clear enough. I don't mean that I want Firebug/DevTools, I mean a tool [that maybe a feature of some kind of in-browser] that outputs all the relevant HTML/CSS for the selected element into a self contained file / to the clipboard.
EDIT2:
When I say outputs all relevent HTML/CSS I mean that I want that element and all it's css rules, and then each parent element with their css rules all the way up to . What I would get as an output would be enough HTML/CSS to open as a standalone page and have the target element rendered and effected by all relevant CSS rules.
Yes, there is a tool/s and ways to do that.
First, with Chrome extension, you can install SnappySnippet from Chrome Web Store. It allows easy HTML+CSS extraction from the specified (last inspected) DOM node. Additionally, you can send your code straight to CodePen or JSFiddle.
Second, CSS Used, other Chrome extension, for extracting CSS with children CSSs.
And third, without extension, if you want CSS embedded in HTML or above extensions is not working for you, you can use any Webkit based browser (like Chrome or Firefox) to run script in console which will add all css to html element and you can easily just copy OuterHTML and it will work anywhere.
var el = document.querySelector(“#yourId”); // change yourId to id of your element, or you can write “body” and it will convert all document
var els = el.getElementsByTagName("*");
for(var i = -1, l = els.length; ++i < l;){
els[i].setAttribute("style", window.getComputedStyle(els[i]).cssText);
}
So, just copy this code to Console (Right click on page->Inspect->Console), change yourid to yourid or set it to "body", run it and then right click on your element and "copy outerHTML"
Do you mean something like Firebug ( Firefox addon )? Or the Debug bar in Chrome ( Press F12 in the browser )?
In Chrome:
Press F12
Click on the loop in the bottom left.
Click on the element
Now you can see all the style.
In the big window you can see other element, and the element under
it.
In chrome, you can right click the page, and then select "inspect element" to view the html code of the page (but in the browser). Then, right click on the element that you want to export, and select "copy as html". Paste it into whatever editor you like. Hope this helps.
Press F12 or right click and go "inspect element" then select element to get the HTML code for the current webpage. Once at that point click the magnifying glass to the left and click on an element of the page using that, that will show you the code used for that specific element, after that you can right click and select "Copy Html" or you can go "Edit as Html" and then copy the code.
You can try to use a tool like Site Sucker for this. I've used it to grab entire websites, but there are settings available that might limit to what you're looking for.
Great question - it was alive and kicking for me today :-)!
Building on the accepted answer (thank you for that!) and this answer, I've got:
var el = document.querySelector("#question > div.post-layout > div.postcell.post-layout--right > div.s-prose.js-post-body"); // change yourId to id of your element, or you can write “body” and it will convert all document
var els = el.getElementsByTagName("*");
for(var i = -1, l = els.length; ++i < l;){
el = els[i]
s = getComputedStyle(el)
for (let styleKey in el.style) {
for (let computedStyleKey in s) {
let computedStyleKeyCamelCase = computedStyleKey.replace(/\-([a-z])/g, v => v[1].toUpperCase());
if ((typeof el.style[styleKey] != "function") && (styleKey != 'cssText')){
if(styleKey == computedStyleKeyCamelCase) {
el.style[styleKey] = s[computedStyleKey];
}
}
}
}
}
P.S.:
The above code should run in the Developer Tools (F12) console (tried it in Chrome) and it will add the inline style to each element
After running you could right click and do Copy / OuterHTML