Puppeteer: How to write XPath for button in puppeteer - puppeteer

var eleLoginButton = await page.waitForXPath("//input[#class='._ant-btn._ant-btn-primary']")
await eleLoginButton.click()
My Code is not getting Excuted if I have written it like this.

You do not need dot for class in XPath. Try this:
var eleLoginButton = await page.waitForXPath("//input[#class='_ant-btn _ant-btn-primary']");
await eleLoginButton.click();

Related

how to url split and use the second element as a new url

I try to split url with '?' and use the second element on html
example:
https://url/page?google.com
the output I want to receive is: google.com
and redirect the page to the output, I'm using webflow so if anyone can help with a full script it will be amazing.
I tried:
window.location.replace(id="new_url");
let url = window.location;
const array = url.split("?");
document.getElementById("new_url").innerHTML = array[1];
but it doesn't work :(
window.location.replace(id="new_url"); is not valid syntax.
window.location.replace(new_url); where new_url contained a valid URL would instantly change the page and ignore all other script after it.
I assume you can use the URL api?
Note
your parameter is non-standard
you need to add protocol (https://) to go to the URL
Here is a complicated version, but using a standard tool
const urlString = "https://url/page?google.com"
const url = new URL(urlString)
console.log(url.toString())
const firstSearchKey = [...url.searchParams.entries()][0][0]; // normally parameter=value
console.log(firstSearchKey)
location.replace(`https://${firstSearchKey}`)
Here is a simpler version
const urlString = "https://url/page?google.com"
const [origin,passedUrl] = urlString.split("?");
location.replace(`https://${passedUrl}`)
Try this
const url = window.location.search.split("?")[1]
window.location.href = url
let url = "https://url/page?google.com"
const regex = /\?(.*)/;
let res = regex.exec(url)
console.log(res[1])
Is this what you want?
const inputUrl = window.location.href // ex. https://url/page?google.com
const splitUrl = inputUrl.split("?") // = ["https://url/page", "google.com"]
const targetUrl = splitUrl[1] // = "google.com"
window.location.href = targetUrl // sets current window URL to google.com

Puppeteer: how to access/intercept a FileSystemDirectoryHandle?

I'm wondering if it's possible within puppeteer to access a FileSystemDirectoryHandle (from the File System Access API). I would like to pass in a directory path via puppeteer as though the user had selected a directory via window.showDirectoryPicker(). On my client page I use the File System Access API to write a series of png files taken from a canvas element, like:
const directoryHandle = await window.showDirectoryPicker();
for (let frame = 0; frame < totalFrames; frame++){
const fileHandle = await directoryHandle.getFileHandle(`${frame}.png`, { create: true });
const writable = await fileHandle.createWritable();
updateCanvas(); // <--- update the contents of my canvas element
const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png'));
await writable.write(blob);
await writable.close();
}
On the puppeteer side, I want to mimic that behavior with something like:
const page = await browser.newPage();
await page.goto("localhost:3333/canvasRenderer.html");
// --- this part doesn't seem to exist ---
const [dirChooser] = await Promise.all([
page.waitForDirectoryChooser(),
page.click('#choose-directory'),
]);
await dirChooser.accept(['save/frames/here']);
//--------------------------------------
but waitForDirectoryChooser() doesn't exist.
I'd really appreciate any ideas or insights on how I might accomplish this!

puppeteer splitwise login not wokring

I have tried multiple examples to get the splitwise login but unable to get it working.
Although, I'm quite new to puppeteer but login felt a simple usecase for understanding puppeteer.
const puppeteer = require('puppeteer')
const screenshot = 'login.png';
(async () => {
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()
await page.goto("https://www.splitwise.com/login", {
waitUntil: 'networkidle2'
});
await page.type('#user_session_email', 'atest')
await page.type('#user_session_password', 'test')
await page.click('[name="commit"]')
await page.waitForNavigation()
browser.close()
console.log('See screenshot: ' + screenshot)
})()
Unfortunately, the page has two forms with identical ids (but different classes) and these forms have inputs with identical ids as well. You just need more specific selectors:
await page.type('form.form-stacked #user_session_email', 'atest')
await page.type('form.form-stacked #user_session_password', 'test')
await page.click('form.form-stacked [name="commit"]')
This does not seem to be a puppeteer issue.
It seems that javascript code in page is actively blocking triggered events somehow.
Are you able to set these values using regular javascript in the console?

Get an attribute of a page element in pupeeter/apify

I could fetch the textContent of a html element in pupeeter:
var website_element = await page.$('a[itemprop="url"]');
var website= await (await website_element .getProperty('textContent')).jsonValue();
yet, sometimes the textContent is not enough, see the following html:
<a itemprop="url" href="https://www.4-b.ch/de/4b-fenster-fassaden/home/">
https://www.4-b.ch/de/4b-fenster-fassad...</a>
the result is obscure: "https://www.4-b.ch/de/4b-fenster-fassad..." with ... at the end.
So, i better get the href attribute.
But when:
var website_element = await page.$('a[itemprop="url"]');
var website = await (await website_element.getAttribute('href')).jsonValue();
The result is TypeError: website_element.getAttribute is not a function
Any suggestion?
There's an easy and fast way to do this using the page.$eval function:
var website = await page.$eval('a[itemprop="url"]', el => el.href);
What page.$eval does is that it first finds an element in the DOM using the provided selector (first argument) and then invokes the callback (second argument) with the found element as its only argument. The return value of the callback becomes the return value of page.$eval() itself.
it works:
var website_element = await page.$('a[itemprop="url"]');
var website = await (await website_element.getProperty('href')).jsonValue();

Puppeteer - How to fill form that is inside an iframe?

I have to fill out a form that is inside an iframe, here the sample page. I cannot access by simply using page.focus() and page.type(). I tried to get the form iframe by using const formFrame = page.mainFrame().childFrames()[0], which works but I cannot really interact with the form iframe.
I figured it out myself. Here's the code.
console.log('waiting for iframe with form to be ready.');
await page.waitForSelector('iframe');
console.log('iframe is ready. Loading iframe content');
const elementHandle = await page.$(
'iframe[src="https://example.com"]',
);
const frame = await elementHandle.contentFrame();
console.log('filling form in iframe');
await frame.type('#Name', 'Bob', { delay: 100 });
Instead of figuring out how to get inside the iFrame and type, I would simplify the problem by navigating to the IFrame URL directly
https://warranty.goodmanmfg.com/registration/NewRegistration/NewRegistration.aspx?Sender=Goodman
Make your script directly go to the above URL and try automating, it should work
Edit-1: Using frames
Since the simple approach didn't work for you, we do it with the frames itself
Below is a simple script which should help you get started
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://www.goodmanmfg.com/product-registration', { timeout: 80000 });
var frames = await page.frames();
var myframe = frames.find(
f =>
f.url().indexOf("NewRegistration") > -1);
const serialNumber = await myframe.$("#MainContent_SerNumText");
await serialNumber.type("12345");
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
The output is
If you can't select/find iFrame read this:
I had an issue with finding stripe elements.
The reason for that is the following:
You can't access an with different origin using JavaScript, it would be a huge security flaw if you could do it. For the same-origin policy browsers block scripts trying to access a frame with a different origin. See more detailed answer here
Therefore when I tried to use puppeteer's methods:Page.frames() and Page.mainFrame(). ElementHandle.contentFrame() I did not return any iframe to me. The problem is that it was happening silently and I couldn't figure out why it couldn't find anything.
Adding these arguments to launch options solved the issue:
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process'
Though you have figured out but I think I have better solution. Hope it helps.
async doFillForm() {
return await this.page.evaluate(() => {
let iframe = document.getElementById('frame_id_where_form_is _present');
let doc = iframe.contentDocument;
doc.querySelector('#username').value='Bob';
doc.querySelector('#password').value='pass123';
});
}