Given I want to record the action being done the page, when clicking on an element
Playwright scrolls the page until the element is on top of the page, even though before the action the element is visible in the viewport.
P.S. the option "scroll: false" does nothing
code snippet:
await Promise.all([
global.page.waitForNavigation(),
global.page.click(global.identifier, { scroll: false })
]);
L.E.:
I want to add some more details about my issue using an example:
So, let's assume I want to do a click action on the "Answer your question" button, and page looks like this:
after the click is performed the page automatically scrolls, putting the button on top of the page, like this:
My expectation is, if the element is in viewpoint, just to perform the action, without scrolling or moving the viewpoint.
I also faced this issue so I resolve this by doing scroll into the view function reference
await page.$eval(ele, (element) => {
element.scrollIntoView();
});
So here's the full code
const playwright = require('playwright');
const moment = require('moment');
(async () => {
const browser = await playwright.chromium.launch({
headless: false,
args: ['--disable-notifications']
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://stackoverflow.com/questions/68127885/playwright-page-click-scrolls-too-much');
await page.waitForSelector('.js-accept-cookies')
.then(() => page.click('.js-accept-cookies') );
let ele = '#submit-button';
await page.$eval(ele, (element) => {
element.scrollIntoView();
});
await page.click(ele);
let date = moment();
await page.screenshot({ path: `example-scroll-${date}.png` });
await browser.close();
})();
Attaching screenshot for reference:
Related
Link: http://quotes.toscrape.com/
Click on the above link and scroll to the bottom. I don't know how to click on the Next button.
My code:
await page.click(".pager > .next > a")
The above code is not working.
I want to know, how to click on this button.
I use below code and can click Next button. The keypoint here is to use waitForSelector to make sure the element you want is available.
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('http://quotes.toscrape.com/');
// Set screen size
await page.setViewport({width: 1080, height: 1024});
// Wait and click on first result
const searchResultSelector = '.next a';
await page.waitForSelector(searchResultSelector);
await page.click(searchResultSelector);
// await browser.close();
})();
refs from doc: https://pptr.dev/#example
I want to save the value 'final' (what I am logging to the console) to the clipboard every time it is updated. I have looked into clipboard.js but cannot find an example of where they didn't use HTML. In all the examples I've seen they press a button in order to do it but I need it to be automatically copied without any HTML. I tried using navigator.clipboard.writeText() but it gave me an error regarding promises and I'm not too sure how to resolve it or if there is a better solution.
const puppeteer = require("puppeteer");
const url = "https://www.google.com/";
async function StartScraping() {
await puppeteer
.launch({
headless: false,
})
.then(async (browser) => {
const page = await browser.newPage();
await page.setViewport({
width: 2000,
height: 800,
});
page.on("response", async (response) => {
if (response.url().includes("Example")) {
const location = await response.text()
let ping1= location.indexOf("Follow:")
const final = location.substring(ping1, ping1+ 10)
console.log(final);
//Copy 'final' to clipboard here
}
});
await page.goto(url, {
waitUntil: "load",
timeout: 0,
});
});
}
StartScraping();
Yes, you can do this.
You don't need any libraries, you can just do this with one line of code.
navigator.clipboard.writeText("text");
I put it in a function:
function copyText(a){ navigator.clipboard.writeText(a); } copyText("text");
This example uses a button (to execute the function):
function copyText(a) {
navigator.clipboard.writeText(a);
}
<h1>Copy text on button click</h1>
<p>Copy text without a form input or any extra js libraries</p>
<button onclick="copyText('Hello World!');">Copy</button>
It doesn't work in this snippet, but if you put it into jsfiddle or a w3schools tryit page, it would work.
I'm trying to fill this login form and submit it like that:
document.querySelector('#username').value="my#email";
document.querySelector('#username').dispatchEvent(new Event('change'));
document.querySelector('#password').value="mypassword";
document.querySelector('#password').dispatchEvent(new Event('change'));
document.querySelector('button[class~="btn-red"]').click();
But the website displays the message that the email and password are empty. I guess its waiting for a key press or something.
How can I simulate that?
You can emit the input event instead of the change event:
document.querySelector('#username').value="my#email";
document.querySelector('#username').dispatchEvent(new Event('input'));
document.querySelector('#password').value="mypassword";
document.querySelector('#password').dispatchEvent(new Event('input'));
document.querySelector('button[class~="btn-red"]').click();
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.boxtal.com/fr/fr/app/utilisateur/connexion', {
waitUntil: 'networkidle2'
});
await page.waitFor('#username');
await page.type('#username','my#email');;
// await browser.close();
})();
If you are using puppeteer you can use the code above to type in an input field
In TestCafe, on click of an anchor tag, I have a redirect to a new page and an event that basically logs the click event to an object.
I'm wanting to test the value of the click event in the object in TestCafe, but because the redirect happens, I lose the object.
Manually I'm able to do this, as I can hold shift while clicking the link and open a new window for the redirected page, but keep the original page in the original window and then see the object in the console.
Trying to figure out if there's a way "simulate" a click, but not do the redirect. Or alternatively, be able to assert somehow immediately after the click, but before the redirect?
mini example:
await t
.click('a') // here it already redirects so I'll lose the object
.expect(object).contains('value')
The following test shows how you can disable and enable navigation for a link:
import { Selector, ClientFunction } from 'testcafe';
fixture `Navigation`
.page `example.com`;
const enableNavigationControl = ClientFunction(selector => {
const element = selector();
element.addEventListener('click', event => window.disableNavigation && event.preventDefault());
});
const disableNavigation = ClientFunction(() => window.disableNavigation = true);
const enableNavigation = ClientFunction(() => window.disableNavigation = false);
test('navigation', async t => {
const link = Selector('a');
await enableNavigationControl(link);
await disableNavigation();
await t.click(link);
// Perform assertions...
await enableNavigation();
await t.click(link);
});
Why is the on click event on anchor not triggering while manually clicking in a debug session from VS Code?
Broadly here is my goal:
Go to linkedin.com using Puppeteer in headful Chrome
Login
Go to linkedin.com/jobs
Attach a click event handler for all the links on the page
Pause the node.js execution after attaching the event handlers
Click the links manually with my mouse to observe this new event handler in action
In code, this is what I got
const puppeteer = require('puppeteer')
async function main() {
const browser = await puppeteer.launch({ headless: false })
const page = await browser.newPage();
await page.goto('https://www.linkedin.com/');
await login(page);
await page.goto('https://www.linkedin.com/jobs/');
await attachLinks(page);
await page.screenshot({ path: "bla" })
browser.close();
};
async function attachLinks(page) {
const bodyHandle = await page.$('body');
await page.evaluate( (body, numLinks=3) => {
let anchors = Array.from( body.querySelectorAll("a") ).
filter( (e, i) => i < numLinks );
for(let i = 0; i < anchors.length; i++) {
let a = anchors[i];
console.log(`Binding for ${a.href}`);
// This event does not trigger!!!!!
a.addEventListener("click", e => {
console.log("some one clicked the link");
e.preventDefault();
e.stopPropagation();
return false;
});
};
}, bodyHandle);
await bodyHandle.dispose();
}
main();
Then using VS Code and node.js debugging support, I put a breakpoint on line await page.screenshot({ path: "bla" }) after the onclick event for <a> tags is attached. In the browser that opens (as headless is set to false), while the code is waiting to be resumed, I clicked the <a> tags in the <body> with my mouse, expecting to see "some one clicked the link" in the headful debug Chrome browser's console. But I dont see a logs either in the browser or in VS Code's Debug console. Am I missing something here?
That's because you are not actually clicking the anchor tag. You've attached an event to it "click" and defined what will happen when we will click it, but you're not actually clicking it. Just add a.click() like
// This event will now trigger
a.addEventListener("click", e => {
console.log("some one clicked the link");
e.preventDefault();
e.stopPropagation();
return false;
});
a.click();
see the name addEventListener, you're attaching an event listener, not actually clicking it