I know how to receive postMessages ,but I am looking to send a postMessage request to a site
Just a Format
const puppeteer = require('puppeteer');
const yargs = require('yargs');
let command = yargs.argv._[0];
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
function sendMessageToContentScriptByPostMessage(data)
{
window.postMessage({cmd: 'message', data: data}, '*');
}
await page.goto(command, {waitUntil: 'networkidle0'});
await browser.close();
})();
So the user can do this, node postmessage.js https://www.example.com
You can use page.evaluate to run things inside the browser. Then you can send a postMessage:
await page.evaluate((data) => {
window.postMessage({cmd: 'message', data: data}, '*');
}, data);
Two things to keep in mind:
the evaluate runs inside the browser, while all the other scripts are inside NodeJS (you can think of remote vs local code, local = NodeJS, remote = Chrome)
because of this, variables inside the evaluate are different than outside. You need to explicitly pass the data to evaluate to move it into the browser context.
Related
(async () => {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto('https://youtube.com')
await page.waitForSelector("#search")
await page.type('#search', 'cheese')
await page.screenshot({path: 'youtube.png'});
console.log('done')
})();
I tried to run this to send me the search results of something but it returns "Uncaught Error Error: Evaluation failed: Error: Cannot focus non-HTMLElement" Any idea what I did wrong and need to fix? I saw a similar post but it didn't have an answer and I know I could just go straight to the page but I want to know how to use the search bar.
It's my first time using Playwright and I just can't figure out how to check if a request is made to the server. I want to press a button that sends request and and validate if it was successful or not. I am using chromium from Playwright and making tests with Mocha and Chai. This is my code:
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
await page.click('text=Send');
// Validate if the request is send
await browser.close();
I may be trying to do it wrong, but I don't have much experience with Playwright, so any help will be appreciated.
You can use page.waitForRequest, using the urlOrPredicate parameter to verify that the request matches your expectation.
I'm not sure I have it clear. As I see it, you'd need to make the requests to the API. You can check it in the docs. For example, after clicking the button:
test('api', async({ request }) => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
await page.click('text=Send');
// your api call(s)
const req = await request.YOUR_REQ_METHOD('https://THE_URL_NEEDED');
// your assertion(s)
expect(req.ok()).toBeTruthy();
});
I'd just add, and I'm not saying this is the case, always consider if you need the use of a browser for achieving your goal.
I am trying to use an asynchronous function to perform a POST request. Once this request has been sent, I wish to close the current window. Below is the code I am using.
async function postData() {
const response = await fetch(destinationUrl, fetchOptions);
return response.json();
}
postData().then(window.close());
The parts work individually, but when combined, the request doesn't seem to be sent before the window closes.
How can I make sure the request is sent before closing the window?
I would like to avoid the use of a timeout if possible.
You have to provide a callback to .then:
async function postData() {
const response = await fetch(destinationUrl, fetchOptions);
return response.json();
}
postData().then(() => window.close());
// or more concise:
postData().then(window.close);
I have a script, which loads a certain address into a child window and works on that. If I cannot access the loaded document I'd like to know whether the browser loaded the Chrome error page because the network or the server is down or I got an error because I did not disable security and site isolation for the actual window. I got the same DOMException{stack: 'Error: Blocked a frame with origin "..." from accessing a cross-origin frame. in both scenario. I thought on using navigator.onLine and/or checking with XHR as possible solutions, but I am not sure if this is possible. I don't want to experiment for days if not necessary. Is there anybody who solved this?
conclusion:
I ended up using a modified version of the accepted answer with async functions:
async function isAlive(url) {
try {
await fetch(url, {mode: 'no-cors'});
return true;
} catch(error){
return false;
}
}
(async function main(){
const addresses = [
'https://google.com',
'https://reallyf4kewebsite.com',
'/',
'https://google.com/foo/bar/baz'
];
const results = await Promise.all(addresses.map((address) => isAlive(address)));
addresses.forEach((address, index) => console.log(address, results[index]));
})();
You can know if a server is alive by doing a no-cors request to it.
But you won't be able to get any more info than that, i.e an error redirect (404, 501, etc.) will be seen as alive.
That is because, while this mode allows us to send requests as if there were no CORS limitations, the Response you'll get is actually opaque, and no other information than "The URL mapped to some response" will be accessible to our scripts.
function isAlive(url) {
return fetch(url, {mode: 'no-cors'})
.then(r => true)
.catch(r => false);
}
isAlive('https://google.com')
.then(r => console.log('google', r));
isAlive('https://reallyf4kewebsite.com')
.then(r => console.log('reallyf4kewebsite', r));
isAlive('/')
.then(r => console.log('stacksnippets', r));
isAlive('https://google.com/foo/bar/baz')
.then(r => console.log('404 redirect', r));
I am using wget to download some images, but sometimes the image does not download entirely (it starts at the top, and then stop abruptly...)
Here is my code :
try {
var img = fs.readFileSync(pathFile);
}
catch (err) {
// Download image
console.log('download')
wget({
url: reqUrl,
dest: pathFile,
timeout : 100000
}, function (error, response, body) {
if (error) {
console.log('--- error:');
console.log(error); // error encountered
} else {
console.log('--- headers:');
console.log(response); // response headers
console.log('--- body:');
//console.log(body); // content of package
var img = fs.readFileSync(pathFile);
and so on...
basically, it tries to find the file located at pathFile, and if he does not exist, I download it on my server with wget. But it seems that wget launch the callback before finishing the download...
Thank you!
It seems that you are possibly responding to some requests but you're using blocking function calls (those with "Sync" in their name). I'm not sure if you realize but that is blocking your entire process for the duration of that operation and will completely ruin any chance for concurrency if you ever need it.
Today you can use async/await in Node that looks synchronous but doesn't block your code at all. For example using request-promise and mz modules you can use:
const request = require('request-promise');
const fs = require('mz/fs');
and now you can use:
var img = await fs.readFile(pathFile);
which is not blocking but still lets you easily wait for the file to load before the next instruction is run.
Keep in mind that you need to use it inside of a function declared with the async keyword, e.g.:
(async () => {
// you can use await here
})();
You can get the file with:
const contents = await request(reqUrl);
and you can write it with:
await fs.writeFile(name, data);
There's no need to use blocking calls for that.
You can even use try/catch with that:
let img;
try {
img = await fs.readFile(pathFile);
} catch (e) {
img = await request(reqUrl);
await fs.writeFile(pathFile, img);
}
// do something with the file contents in img
One could even argue that you could remove the last await but you can leave it to wait for potential errors to be raised as exception on the promise rejection.