couldn't grab input element from a website - javascript

so I'm trying to get an input element from Twitter but when I run it, it keeps giving me an error like this in the node terminal, as a result, a browser window made from this code will close itself because it doesn't find the right input selector. how do I grab the right kind of input?
Error: No element found for selector: input[name="text"]
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false,
})
const page = await browser.newPage();
page.setViewport({
width: 1280,
height: 800,
isMobile: false
})
await page.goto("https://twitter.com/i/flow/login");
await page.type('input[name="text"]', 'username', {delay: 25})
})();
i tried different selectors including class attribute but still gets error

you need to waitForSelector to appear on the page before typing. That is why you got an error, it couldn't find the element.
await page.waitForSelector('input[name="text"]');
await page.type('input[name="text"]', 'username', {delay: 25})

Related

Iframe not loading properly in puppeteer

I am trying to parse a website using puppeteer, everything works well but iframe does not load properly.
This is how it loads
Here is my code
args: [
"--no-sandbox",
],
});
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 600 })
// await waitForFrame(page);
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 0,
});
await page.evaluate(({ applicationUrl}: any ) => {
// Here i want to evaluate iframes
})
When i try to log iframes, i don't get the actual iframe link on my parsed website
Also i don't see the iframe tag in parsed website
But When i look into the actual page, i can see the iframe link
and also the iframe tag
Here is the link to actual page which i am trying to parse
https://leza.notion.site/Trade-log-721b1ebb4cc74175abb55408b6f2d0c3
Any help would be highly appreciated
it's lazy loaded
try scrolling around and then wait some for iframe to load, and then get the iframe:
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 0,
});
await page.evaluate(async() => {
const scroll = document.querySelector('.notion-scroller');
scroll.scrollBy(0, 900);
document.querySelector('.notion-video-block').scrollIntoView();
});
// wait some for iframe to load..
await page.waitFor(5000);
const iframeSelector = 'iframe';
const frameHandle = await page.$(iframeSelector);
const src = await page.evaluate(el => el.src, frameHandle);
console.log(src);

When I start puppeteer, the window has an empty white border

when I start puppeteer, I get a really weird empty border. The whole thing looks like this:
Is there a way to get the empty border away, or is this normal?
Try using defaultViewport: null,
You can use the default page opened by puppeteer, like this:
async function launchBrowser() {
const browser = await puppeteer.launch({
headless: false,
executablePath: process.env.CHROMIUM_PATH,
defaultViewport: null,
ignoreHTTPSErrors: true
});
return browser;
}
const browser = await launchBrowser()
const defaultPages = await browser.pages()
const page = defaultPages[0]
await page.goto('https://www.google.com.my/')
Here the window will also be having only one tab and not that empty tab.

Node using test for UI login

I use the following blog to use the playright
login and I need something similar to use for my app, when I use the headless:flase
I see it opens the UI with the user password in however, it doesnt click on the logon button, I adopt the code I try with the following , am I missing something?
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://app.com');
await page.fill('input[type="text"]', 'user#test.com');
await page.fill('input[type="password"]', 'Abcd1234!');
// page.click('div[data-testid="LoginForm_Login_Button"]');
page.click('div[id="logOnFormSubmit"]');
}
)();
You are currently using
page.click('div[id="logOnFormSubmit"]');
There is no div in your given code example with that ID, but instead there is a button. You'd need to change that line to reflect this. The final code would look like below.
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://app.com');
await page.fill('input[type="text"]', 'user#test.com');
await page.fill('input[type="password"]', 'Abcd1234!');
// page.click('div[data-testid="LoginForm_Login_Button"]');
page.click('button[id="logOnFormSubmit"]');
}
)();

How to use Puppeteer with Stripe Elements

Been slamming my head against this for a while now and no idea why this is happening.
I'm using react-stripe-elements and trying to write a test using Puppeteer. I simply cannot get Puppeteer to fill in the Card Elements.
I've tried a few approaches
Approach 1
I try to select the input by its name and then any input on the page by its class
await page.$eval('input[name="cardnumber"]')
await page.$eval(".InputElement");
I'm told that there's
Approach 2
I then tried to access the actual frame, my reasoning being that its technically a page with a different origin. Again, nothing happens. Now, strangely, when I try and print out the contents of the frame, nothing happens again.
const cardExpiryFrameHandle = await page.$('iframe[name="__privateStripeFrame5"]')
const cardExpiryFrame = await cardExpiryFrameHandle.contentFrame()
const test = await cardExpiryFrame.content()
console.log(test);
When I console log out cardExpiryFrame, it exists. This should fit the API defined here https://pptr.dev/#?product=Puppeteer&version=v3.3.0&show=api-class-frame, but it absolutely refuses to.
I also added arguments to disable some security features because I tracked down an issue that said that this might be a problem. I do so like this
module.exports = {
server: {
command: `npm run-script start:test:server`,
port: 3000,
launchTimeout: 100000,
debug: true,
args: ['--disable-web-security', '--disable-features=IsolateOrigins,site-per-process'],
},
launch: {
headless: false,
},
}
Approach 3
I then tried to mimic what a human would do and clicked the div and then tried to type out the test card number.
await page.click(getClass(paymentFlowCardInput))
await page.keyboard.type('4242424242424242', { delay: '50' })
Again no luck. No errors.
Now I'm out of ideas - what do I do?
A good solution for this is using tab to switch to the next input. In my test I have an input for the cardholder name and I then tab to the CardElement component.
describe('Test Input', () => {
test('Filling out card payment form', async () => {
let browser = await puppeteer.launch({
headless: false,
slowMo: 100
});
let page = await browser.newPage();
page.emulate({
viewport: {
width: 1280,
height: 1080
},
userAgent: ''
});
await page.goto('http://localhost:3000/asd/payment-requests/50-eur-by-2021-01-15t1200');
await page.waitForSelector('#input-name');
await page.click('input[name=card_name]')
await page.type('input[name=card_name]', 'Joe Bloggs')
await page.keyboard.press("Tab");
await page.keyboard.type(card.number, { delay: 500 })
await page.keyboard.type(card.month, { delay: 50 })
await page.keyboard.type(card.year, { delay: 50 })
await page.keyboard.type(card.cvc, { delay: 50 })
await page.keyboard.type(card.zip, { delay: 50 })
browser.close();
}, 90000);
});
You're likely running into this issue because your test isn't waiting for the CardElement to mount (and finish its animations) or, the animations are slower than your delay. Here's an example of a puppeteer test which takes those transitions into account for your reference: https://github.com/stripe/react-stripe-elements/issues/137#issuecomment-352092164

Puppeteer doesn't show a calendar that is shown after clicking a text field

I'm using Puppeteer for doing some web scraping and I'm having troubles. The website I'm trying to scrape is this one and I'm trying to create a screenshot of a calendar that appears after clicking the button "Reserve now" > "Dates".
const puppeteer = require('puppeteer');
const fs = require('fs');
void (async () => {
try {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('https://www.marriott.com/hotels/travel/reumd-le-meridien-ra-beach-hotel-and-spa');
await page.setViewport({ width: 1920, height: 938 });
await page.waitForSelector('.m-hotel-info > .l-container > .l-header-section > .l-m-col-2 > .m-button');
await page.click('.m-hotel-info > .l-container > .l-header-section > .l-m-col-2 > .m-button');
await page.waitForSelector('.modal-content');
await page.waitFor(5000);
await page.waitForSelector('.js-recent-search-inputs .js-datepick-container .l-h-field-input')
await page.click('.js-recent-search-inputs .js-datepick-container .l-h-field-input');
await page.waitFor(5000);
await page.screenshot({ path: 'myscreenshot.png'});
await browser.close();
} catch (error) {
console.log(error);
}
})()
This is what myscreenshot.png should contain:
but I'm getting this instead:
As you can see, myscreenshot.png doesn't contain the calendar. I don't understand what I'm doing wrong since I click on the right node and I even give time enough to it for loading everything.
Thank you in advance!
Edit: I forgot to say that I have also tried Puppeteer recorder in order to achieve this and I haven't had luck either.
As you have many .l-h-field-input elements, I would try being more specific there.
This worked for me:
await page.click('.js-recent-search-inputs .js-datepick-container .l-h-field-input');

Categories