How does testcafe decide an iframe has loaded? - testing

I'm currently on the latest package 1.18.4 and having issues switching to an iframe during test execution.
Each time t.switchToIframe() is called, the following error is displayed:
Content of the iframe in which the test is currently operating did not load.
This happens even though i can clearly see the iframe has loaded, even placing a length wait of 60 seconds when landing on the page for testing purposes.
This rough code below should be runnable and reproduce the problem:
import { Selector, t } from "testcafe";
fixture(`Quick Test`);
test
.page(`https://www.terrific.ie/dealer/bradys-of-castleknock/finance/45784/13295`)(
`Quick Test`,
async () => {
await t
.click(`.submit-outer`)
.expect(Selector(`.car-summary-box`).visible)
.ok()
.expect(Selector(`.cw-finance-plugin.plugin-loaded`).visible)
.ok()
.switchToIframe(`.cw-finance-plugin.plugin-loaded`)
.click(`.cw-checkmark`)
.debug();
});

In general, there are two steps to switch to iframe. The first step is getting a selector with an iframe, but if the selector doesn't exist, you will get another error. The next step is getting contentWindow with a native getter. The error probably occurs on this step, but I can't reproduce this case with your iframe example. Could you share a full test example that illustrates this error?
Also, you put the content of the iframe between the tags, but it doesn't work like this. You need to set the path to the document in the src attribute of the iframe.

Related

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();
}
});
}

Salesforce's iframes

In order to support new lightning of salesforce, I'm trying to rewrite existing e2e tests. We have an integrated app, which opens in inframe in both cases (classic design and new lighting). In the case of old site design, we have to dig into the second level of nesting
<iframe ...>
...
<iframe id='my app'>
In the case of the newest design, yet another one level of nesting was added (my iframe is also in the deep).
I'm facing the problem, that I'm not able to switch to the second iframe. I always get "The iframe in which the test is currently operating does not exist anymore." Even if I want to await the simplest Selector with "div" element for example.
await t.expect(Selector('div').find('iframe').exists).eql(true);
await t.switchToIframe(Selector('div').find('iframe'));
const nextIframe = Selector('div');
const dom = await nextIframe(); <--- here it throws
I've checked the the first one selector, it returns exactly what I want.
What can cause my problem?

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?

How to perform feasible web smoke test with Selenium WebDriver?

I have been doing some research on feasible and faster web page loading test with Selenium. A general idea of smoke testing is to click and navigate through the whole site to make sure the pages load properly. I was initially thinking to use some kind of ways to capture the http status code through some kind of http libraries since Selenium does not have any native support for that. But, I found it is not what I want since it will simply return Each and Every links of the site and most of them will be the ones I do not want. So the best way will be to perform actual click and take pages in return. The problem there is the execution time it will take. However, that’s what I am doing currently. Splitting the whole application into different modules and click through all VISIBLE links and take page objects in return with known selector. I am using FindElements() method to grab all the links of a page and click back and forth to test page load. I am doing something like the following:
Is there a better way to improve the performance?
WebElement deliveredChartDailyFocus = driver.findElement(By.id("delivered-chart-daily"));
deliveredChartDailyFocus.click();
// Get a list of all the <rect> elements under the #delivered-chart-daily element
List<WebElement> children = deliveredChartDailyFocus.findElements(By.tagName("rect"));
WebElement elementToClick = null; // variable for the element we want to click on
for (WebElement we : children) // loop through all our <rect> elements
{
if (we.isDisplayed())
{
elementToClick = we; // save the <rect> element to our variable
break; // stop iterating
}
}
if (elementToClick != null) // check we have a visible <rect> element
{
elementToClick.click();
}
else
{
// Handle case if no displayed rect elements were found
}
I would never call process of verification of every single link 'smoke testing'. For example how ISTQB defines this "A subset of all defined/planned test cases that cover the main functionality of a component or system, to ascertaining that the most crucial functions of a program work, but not bothering with finer details". And ths actually mean to exacute some meaningful scenarios and check some small flow/piece of functionality. Only clicking every link will check correctness of links but not computations or logic performed by server side. As for improving speed of passing tests you can consider running tests in parallel.

Selenium: Ajax Testing

Please brief me about the Ajax testing with selenium RC.
As in Ajax element not reflect on the view-source, but using firebug we can see the changes in HTML source code.
There are two methods associated with it Ajax testing..
1-The method "waitForCondition (java.lang.String script, java.lang.String timeout), to provide script we have to create a java script by own or it should be the same Ajax script/java script present on the web page.
Please correct me if i am wrong on below point..
2-The method "waitForElemantPresent(Locator)", We check the Element in the firebug and check the same in this method is self waitForElemantPresent(Locator).
Let me know if anything else I am missing testing Ajax application.
I got help on this from one article and with help of #Hannibal
http://agilesoftwaretesting.com/?p=111
JQuery: “jQuery.active”
Prototype: “Ajax.activeRequestCount”
Dojo: “dojo.io.XMLHTTPTransport.inFlight.length”
So if there is Ajax call we can use second option.
selenium.waitForCondition(
"selenium.browserbot.getCurrentWindow().jQuery.active == 0",
timeout);
To answer your first point, yes waitForCondition(javascript,timeout) will run the javascript till it returns a true value OR when timeout happens. You should take a look at the api documentation for this as you need to use browserbot to run the script in your application window. Link to API documentation is here
In Selenium 1, one way by which you can handle the Ajax conditions are by creating custom functions which will wait till the condition is met or till a timeout happens. While a normal Selenium.isElementPresent will fail immediately if the element is not present, your custom function will wait for some more time (the time for Ajax to load) before it fails. As an example you can refer the following custom method for isElementPresent. This is written in JAVA, you should be able to use the same logic in the programming language that you use.
public boolean AjaxIsElementPresent(String elementToLookFor, int timeOutValueInSeconds){
int timer=1;
while(timer<=timeOutValue){
if(selenium.isElementPresent(locator))
return true;
else
Thread.sleep(1000);
}
return false;
}
This method will return a boolean false if the element is not present even after the specified timeoutValue. If it finds the element within the timeoutvalue then it returns a true.
I have seen some in built functions for AjaxCondition handling in Selenium 2. But I have not used it. You can refer to Selenium 2 code base