I have headless off and I want to wait untill user redirect to some page. I could use waitForRequest from puppeteer API but I don't know exact url it just must pass few circumstances.
So I use waitForFunction and check circumstances there but when I redirect to correct URL then I need to refresh page to pass circumstances for some reason.
My code is:
try {
await page.waitForFunction(() => {
if(window &&
window.location &&
window.location.hostname) {
const host = window.location.hostname.split('.');
if(!host.includes('www') &&
!host.includes('new') &&
host.includes('margonem') &&
host.length === 3) {
return true;
}
}
}, {
polling: 200,
timeout: 0
})
} catch (e) {
console.log(e);
}
and when I redirect to URL which pass all of above if's then I need to reload page to actually see that it return true. Why it works like this? I don't want user to be forced to refresh page after he enter correct one.
I have headless off and I want to wait untill user redirect to some page.
just use waitForNavigation().
In combination with a click make sure you use this pattern:
const [response] = await Promise.all([
page.waitForNavigation(waitOptions),
page.click(selector, clickOptions),
]);
waitForNavigation also returns a response object that you can then inspect
I could use waitForRequest from puppeteer API but I don't know exact url it just must pass few circumstances.
in this case puppeteer injects the request as argument and you can just test this in your lambda function. For example:
page.waitForRequest(request => {
return request.url().includes('margonem') && request.method() === 'GET'
})
The simplest way I have found is using waitForFunction, it is simple to modify to fit your specifications as well as compact.
await page.waitForFunction("window.location.pathname == '/Welcome.aspx'")
Sometimes we need to wait until we reach a specific URL.
The best way to handle it is
let holdProgress = true;
while (holdProgress) {
await page.waitFor(300);
if (page.url().includes('/env-selector')) {
holdProgress = false;
}
}
Related
I'm using puppeteer to navigate my website. I want to wait for an api that sometimes gets called and sometimes not. I'm using
await page.waitForResponse((response =>response.url().includes(myurl)), { timeout: 1000 });
to wait for that api. This works fine when the api gets called, but whenever the api doesn't get called, it crashes and the page isn't same anymore. So, I want to deep copy the page so that I can just check for the api via it's copy and even if that page gets damaged. I will have another that I can use.
I think you don't need to copy your page. That's probably not doable very easy and seems like a bit of overkill. Instead, preventing the page from crashing would be a simpler approach.
Try something like this:
async function waitForApi(url, timeoutMs) {
try {
console.log('waiting ', timeoutMs+'ms for special API. url:', url);
const opts = { timeout: timeoutMs || 1000 };
await page.waitForResponse(response => response.url().includes(url), opts);
console.log('Special API was called!.');
return true;
} catch(err) {
console.log('Special Api was appearantly not called. (Or may be failed.. Error:', err);
return false;
}
}
// example call of waitForApi ..
const myUrl = '...'
const apiCalled = await waitForApi(myUrl, 1000)
if(apiCalled) {
// do stuff if you want to..
} else {
// do stuff if you want to..
}
This should now log if the api was called or not and when needed you can handle the cases differently.
Im trying to clear my session when the user leave my site.
when i try to do like below using 'beforeunload' event, even when i try to give enter on my site/application url also my handleBeforeUnload is getting called. Ideally i want to clear if the url(host/origin) is entered is different from my site then only i want to clear my session.
how to escape calling handleBeforeUnload - if the user enter my site specific urls ? or any other possible solution to achieve this request would be appreciated.
Below code i tried with my app.js
const getAppOrigin = window.location.origin;
useEffect(() => {
window.addEventListener('beforeunload', handleBeforeUnload);
return () => {
window.removeEventListener('beforeunload', handleBeforeUnload);
};
}, [getAppOrigin]);
const handleBeforeUnload = ev => {
if (ev || window.event) {
// clear sessions code here
}
};
I am trying to dump out a few key measurements to console when my test runs, rather than getting them from the reporter output, but I can't see how to grab the time taken for the last step to execute. Here's a simplified version based on the docs for request.timing() but I don't think that what I'm doing is classed as a request:
const { test, expect } = require('#playwright/test');
test('ApplicationLoadTime', async ({ page }) => {
// Wait for applications to load
await page.waitForSelector('img[alt="Application"]');
// Not working! - get time for step execution
const [fir] = await Promise.all([
page.click('text=Further information requested'),
page.waitForSelector('img[alt="Application"]')
]);
console.log(fir.timing());
});
The click on "Further information requested" causes the page to be modified based on an AJAX call in the background and the appearance of the Application img tells me it's finished. Is this possible or do I need to rely on the reports instead?
fir is going to be undefined in your code as page.click() doesn't return anything. You need to wait for the request whose timing you're interested in, use page.waitForEvent('requestfinished') or waitForNavigation:
const { test, expect } = require('#playwright/test');
test('ApplicationLoadTime', async ({ page }) => {
// Wait for applications to load
await page.waitForSelector('img[alt="Application"]');
const [fir] = await Promise.all([
// Wait for the request
page.waitForEvent('requestfinished', r => r.url() == '<url of interest>'),
page.click('text=Further information requested'),
page.waitForSelector('img[alt="Application"]')
]);
console.log(fir.timing());
});
I use linking for opening my app from the browser.
When I tap the link for first in-browser my app run but incoming URL don't clear after that and linking.GetInitialUrl() always run with that URL.
My schema is myapp://host and my URL on the web is myapp://host/ok
I click on my URL and linking.getInitialUrl() works but when next time I'm back to My screen linking.getInitialUrl() return my web URL without open web page by me.
componentDidMount() {
Linking.getInitialURL().then(url => {
if (url) {
alert(url)
}
})
.catch(err => {
console.error(err);
});
Linking.addEventListener('url',this.handleOpenURL);
}
componentWillUnmount() { Linking.removeEventListener('url',this.handleOpenURL);
}
handleOpenURL = (event) => { // D
this.linkFunc(event.url);
}
Since you are calling getInitialURL method in componentDidMount method without checking if the app is already loaded or not. Your alert(url) will get triggered whenever that component is loaded again.
To solve the problem, you have to call getInitialURL in the root component that will never be loaded again after the app is loaded.Or you can use a global variable to mark the status of your app whether it is already loaded or not.
if(!InMemoryData.appLoaded){
Linking.getInitialURL().then(url => {
this._navigate(url);
InMemoryData.appLoaded = true;
});
}
I am trying to simulate the user operation on CefSharp(OffScreen) using JavaScript.
Once I load the page (https://www.w3.org),
I am trying to search in the search bar,
click the search button
open first result
So I have used,
await browser.EvaluateScriptAsync("document.getElementsByName('q')[0].value = 'CSS';");
await browser.EvaluateScriptAsync("document.getElementById('search-submit').click();");
await browser.EvaluateScriptAsync("document.getElementById('r1-0').click();");
But the issue I am facing is, to take screenshot, I have to use Thread.Sleep(x) in between and at the end for the pages to load before doing the next operation or take the screenshot.
Is there anyway to avoid the SLEEP and detect when the loading is done, to do the next operation?
I tried ExecuteScriptAsync also, same issue with that also.
You can modify and use the LoadPageAsync() function from the OffScreenExample for this purpose.
Just replace alter the parameters by removing the url as you wont be using it, and remove the if statement using the url.
Then on calling the LoadPageAsync after EvaluateScriptAsync with the corresponding browser object.
The Function will look like this after modification.
public static Task LoadPageAsync(IWebBrowser browser)
{
var tcs = new TaskCompletionSource<bool>();
EventHandler<LoadingStateChangedEventArgs> handler = null;
handler = (sender, args) =>
{
if (!args.IsLoading)
{
browser.LoadingStateChanged -= handler;
tcs.TrySetResultAsync(true);
}
};
browser.LoadingStateChanged += handler;
return tcs.Task;
}
Usage will be like,
await browser.EvaluateScriptAsync("document.getElementsByName('q')[0].value = 'CSS';");
await browser.EvaluateScriptAsync("document.getElementById('search-submit').click();");
await LoadPageAsyncCompleted(browser);
await browser.EvaluateScriptAsync("document.getElementById('r1-0').click();");
await LoadPageAsyncCompleted(browser);