How to give Fixed wait in playwright With out any condition Like we had in cypress : Cy.wait(600) - automation

How to give Fixed(Implicit Wait) wait in playwright
With out any condition
Like we had in cypress :
Cy.wait(600);
Thank You
Like we had in cypress :
Cy.wait(600);

To give a fixed wait in Playwright without using any conditions, you can use the page.waitForTimeout method. This method will pause the script for a specified amount of time before continuing.
await page.waitForTimeout(2000); // waits for 2 seconds
You can also use the page.waitForFunction method with a function that returns true after a certain amount of time. For example:
await page.waitForFunction(() => {
const now = Date.now();
return now - start > 2000;
});
This will wait for 2 seconds before returning true.
Note that these methods should be used sparingly as they can cause delays in the script execution. It is generally better to use specific conditions to determine when to continue, such as waiting for a specific element to be present or for a page to load.

This is 5 sec timeout
await new Promise(resolve => setTimeout(resolve, 5000));

Avoid using hard waits with playwright!
Issue with Hard waits:
Hard waits do only one thing , they simply wait for specified time without considering any application actual response time which is very rigid approach.
See the below example:
await page.waitFor(5000); // hard wait for 5000ms
This will wait for 5 seconds regardless of actual response time which may be less or more than 5 seconds which is bad in both cases as in first case it has to wait unnecessary for longer time where object is already loaded and in second scenario it will fail after waiting unnecessary for 5 seconds if object is not going to load at all in failing scenario.
Recommended Approach
In-built waits
Playwright has in-built waiting mechanism on navigation and page interactions. As they are part of playwright itself , it is better to use them and customize it if required.
Explicit waits
There is another way to handle waits explicitly only in scenarios where auto-waiting is not a sufficient or efficient approach to handle depending on specific scenarios but in general it should be avoided if auto-waiting is enough for the requirement.
Waiting for page navigations and API responses
1)page.waitForNavigation to wait until a page navigation (new URL or page reload) has completed.
2)page.waitForLoadState This waits until the required load state has been achieved.
3)page.waitForURL This waits until a navigation to the target URL.
4)page.waitForResponse waits till the response from the given API is received.
Wait for element
In lazy-loaded pages, it can be useful to wait until an element is visible with locator.waitFor(). Alternatively, page interactions like page.click() auto-wait for elements.
// Navigate and wait for element
await page.goto('https://example.com');
await page.getByText('Example Domain').waitFor();
// Navigate and click element
// Click will auto-wait for the element
await page.goto('https://example.com');
await page.getByText('Example Domain').click();
Waiting on page events
We can also directly wait on page events using page.waitForEvent.
Customized Wait Function
At last we can also write (if really needed) customized wait functions using WaitForFunction for very specific scenarios or specific applications or controls.

Related

Wait untill Page_loaded in selenium

I am new to selenium and building a project (python + selenium). I have inserted a custom wait in code like time.sleep(10)
The thing i am trying to impliment is the code should be block untill a page has been loaded fully and same after button clicks.
I have gone through few reading like
implicit wait
explicit wait
wait untill an element appears up (select by id or something else )
Is there any way to block the code untill a page has been loaded fully. (I do not have any condition upon which i can wait for wait untill). I can not use stuffs implicit wait or explicit as there is no fix time for completion of loading a page
def run(self):
self.browser.get('url')
# here it should wait untill the page has been loaded fully
time.sleep(10)
element = self.browser.find_element_by_css_selector('some-css-selector')
https://www.selenium.dev/documentation/en/webdriver/page_loading_strategy/
normal This will make Selenium WebDriver to wait for the entire page
is loaded. When set to normal, Selenium WebDriver waits until the load
event fire is returned.
By default normal is set to browser if none is provided.
so this is done automatically as page load strategy is normal by defaul ,
But it won't consider asynchronous elements taht loads after the page get loaded , if you want to explicitly wait for some asynchronous element use explicit wait as:
WebDriverWait(driver,15).until(EC.presence_of_all_elements_located(By.CSS_SELECTOR,"some-css-selector"))

Click on element if exists

I want to use setInterval and to try for five times to check if element exists (a button). If it exists, I want to click it and to proceed after it and, if not, I want to just proceed.
How to do so?
This is not the correct way with webdriver that is the underlying API in UIVeri5. The right way is to use the browser.driver.wait() with a predicate that checks for the condition.
But such polling should not be necessary at all with UIVeri5 when working against a UI5 application because UIVeri5 handles the waiting automatically. With the limitation that this magic works only in UI5 apps because it depends on the UI5 runtime to detect when the UI5 app is ready. So when writing tests for UI5, you don't need any pollings, you just write element(by.control()).isDisplayed() and it works fine and perfectly reliable. The check will happen at the correct time - when ui5 app is fully rendered and no polling is necessary.
Based on #Max, I am just writing the answer in a more dummy proof way:
If one needs to check if a button or something else is displayed, isDisplayed() should be called. isDisplayed() is a promise and, if the element is displayed, then in the then() resolution the continuation should be called. If the element is not displayed, the callback should be called in the catch() resolution of the promise.
Example:
iCheckForElementAndContinue: function(callback) {
element.isDisplayed()
.then({
// Element is found
if (callback) {
callback();
}
})
.catch({
// Element is not found
if (callback) {
callback();
}
});
}

Selenium tests fail with azure pipeline sometimes and pass locally

Test cases fail while not finding a link or any validation messages after a button click.
I used explicit waits for page to load:
var waitForDocumentReady = new WebDriverWait(WebDriver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (WebDriver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
For wait specific div of validation messages:
WebDriverWait wait = new WebDriverWait(WebDriver, TimeSpan.FromSeconds(10));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.ClassName("validationErrors")));
But test cases pass sometimes with pipeline and fails sometimes.
I would recommend following:
When ever your tests fail take a snapshot at that moment.
sometimes when you run your tests locally the network communication
is a bit faster than running on server. Which means a spinner or a
loading control may not appear locally because results were retrieved
fast enough but the loader will appear when there is delay from
server in sending the response to client.
If you are trying to run your tests in FF headless on remote grid
setup then it is not yet stable in my experience.
Identify the pattern in failed scenarios which frequently fail and
try and run them multiple times in a loop and identify the pattern of
failure. In one of my case there was an actual bug in the performance
of the application which used to get reproduced whenever the tests
ran immediately in bulk
I was having this issue, except my test would always fail in Azure Pipelines but pass locally. Not running in "headless" mode fixed my problem. To do this, make sure "Test mix contains UI tests" is checked in your "Visual Studio Test" task.
There are a couple of things you need to take care as follows:
Test cases fail while not finding a link or any validation messages after a button click: A lot depends on the attributes of the button. In case the button contains either of the following attributes/events the DOM Tree would be getting updated and subsequently trying to find the desired element may fail:
onclick() event:
<button onclick="myFunction()">Click me</button>
jQuery click() Event:
$("p").click(function(){
alert("The paragraph was clicked.");
});
So after a button click, to find the desired element you need to induce you have to induce WebDriverWait for the ElementExists().
You can find a relevant discussion in ExpectedConditions.ElementIsVisible returns TimeoutException even when element is present
ExecuteScript("return document.readyState").Equals("complete"): This line of code is not that effective to ensure if the desired element(s) are present/visible/interactable with in the HTML DOM.
You can find a relevant discussion in Do we have any generic function to check if page has completely loaded in Selenium
However to wait for specific div with ElementExists() should have worked. The relevant HTML would have helped us to analyze what went wrong. However, if the validationErrors related element is based on HTML5 Constraint validation then you have to use the GetAttribute() method.
You can find a relevant discussion in How to handle html5 constraint validation pop-up using Selenium?

Behat + selenium 2 wait for page to load

Is there a way to reliably wait for pages to load when using Behat with Mink using the Selenium2Driver?
I've inherited some legacy tests that wait like this:
Background:
Given I am on "http://test.example.com"
And I wait for "20000"
Given I click on the element with css selector ".button1"
And I wait for "30000"
Given I click on the element with css selector ".button2"
And I wait for "30000"
Given I click on the element with css selector ".button1"
And I wait for "10000"
i.e. just this single test takes 1minute 30seconds.
What I'd like to do is have a generic way of waiting for the previous click to result in a page load, without having to wait a large fixed amount of time each time.
All of the suggestions I can see for waiting for page load, all refer to checking that a particular page element is loaded.
However these tests run against a variety of legacy websites, where there isn't always a standard element that can be checked to be present, so I'm hoping to use a more generic method.
You can use a wait method with javasccript condition like:
/**
* #When /^wait for the page to be loaded$/
*/
public function waitForThePageToBeLoaded()
{
$this->getSession()->wait(10000, "document.readyState === 'complete'");
}
Another good practice is to have a method that waits for the element, if element is found returns the element object else it will throw an exception.
For the click method you can have something like this:
$this->waitForElement("css_selector")->click();

How to wait until the the page loads in Selenium IDE other than waitforpageload?

I have a problem when running the test cases because the time take for loading the page is different in each time. I have tried WaitforPageLoad and also checking for visual elements but it was not helping.
WaitforPageLoad always wait for specific seconds and checking visual elements wont work all the time since after loading the page there won't be any new elements in some pages.
Could anyone suggest a better idea ?
You could increase the amount of time you wait for a page load:
setTimeout(timeout)
Arguments:
timeout - a timeout in milliseconds, after which the action will return with an error
Specifies the amount of time that Selenium will wait for actions to complete.
Actions that require waiting include "open" and the "waitFor*" actions.
The default timeout is 30 seconds.
This might help. It's a bit unclear what your goal is.
Use the Explicit Wait on your action. For instance:
// Tell webdriver to wait
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(4));
// Test the autocomplete response - Explicit Wait
IWebElement autocomplete = wait.Until(x => x.FindElement(By.ClassName("ac-row-110457")));