Reload page if element does not show - Codeception - codeception

So I'm trying to make codeception reload my page if it does not see an element.
if ($I->dontSeeElement('body > div.site > main > header > h1'))
{
$I->reloadPage();
}
I have this set in the _after function.
But every time I run my test, it throws me an error.
My logic is: If it does see that element, it should just move on. If not, then reload page.

You may want to extend your acceptance tester class with something like this:
public function reloadIfElementNotFound($selector)
{
try {
$this->seeElement($selector);
} catch (\PHPUnit_Framework_ExpectationFailedException $e) {
$this->reloadPage();
$this->seeElement($selector);
}
}
So, it will try to "see" an element, and if it's not found then a \PHPUnit_Framework_ExpectationFailedException will be thrown, which you're going to catch and then reload the page. Also, make sure that the element is then visible after the reload. However, if it's still not visible after the reload, then the exception will be thrown again and break the test, which - I guess - would be the desired behavior.
In your test you'd then simply use:
$I->reloadIfElementNotFound('body > div.site > main > header > h1');

Related

chromeless- Clicking on an element in the next page is not working

On one of my tests I log in and move to the next page.
In the next page when I try to click on the profile element with .click nothing seems to be happening.
When I use the .exists function it returns false.
Why can't chromeless recognize element after changing the DOM?
async func(){
try {
this.chromeless
.goto(this.url)
.click(this.switchToLogIn)
.type(this.email, this.emaillAddressInput)
.type(this.password, this.passwordInput)
.click(this.logInButton )
.click(this.myProfile)
.screenshot()
}
catch(err) {
console.log(err)
}
Anything that was not already available in the DOM tree when the previous action in the chain was performed (with the exception of goto() and possibly some other methods) has to be waited for using the wait() method.
So, assuming that this.myProfile is a CSS selector string for an element to be clicked:
// Unchanged code omitted
.click(this.logInButton)
// Since the previous click loads a new page and/or shows new content, we need to wait
.wait(this.myProfile)
.click(this.myProfile)
Alternatively, the implicitWait Chromeless constructor option could be set to true, as long as that does not affect anything else negatively.

see if the div is present or not in geb

We are using Geb for automation. I have spinner loaded before every page gets loaded. we are using waitFor() , but it takes a long time and the scripts are getting run more than the specified time.The DOM element is
<div classname="loader"></div>
i tried to see if the element is present.
if(!$(".loader").displayed== true)
{}
But i am getting error as ,
geb.waiting.WaitTimeoutException: condition did not pass in 40.0 seconds (failed with exception)
at geb.waiting.Wait.waitFor(Wait.groovy:138)
at geb.waiting.DefaultWaitingSupport.doWaitFor(DefaultWaitingSupport.groovy:51)
at geb.waiting.DefaultWaitingSupport.waitFor(DefaultWaitingSupport.groovy:46)
at geb.Page.waitFor(Page.groovy:516)
at geb.Browser.methodMissing(Browser.groovy:206)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:56)
at loaderSpec(loaderSpec.groovy:415)
Caused by: Assertion failed:
$(".loader").displayed== false
| | |
| true false
[[[ChromeDriver: chrome on XP (1b3943691dd96ebaf9098b1720c87ee9)] -> css
selector: .loader]]
at loaderSpec(loaderSpec.groovy:415)
at loaderSpec(loaderSpec.groovy:415)
at geb.waiting.Wait.waitFor(Wait.groovy:127)
... 6 more
I am not sure how to check if the div is present or not present. If I extend the time to wait for, I am getting element not found error.
Kindly let me know your input.
Are you checking that the div is visible while you are waiting for the spinner to go away?
I've had an issue exactly like this that plagued me. Here is the solution my coworkers and I came up with:
try{
waitFor(10) { element.isDisplayed() } //wait for spinner to kick in
waitFor() { !element.isDisplayed() } //wait for spinner to go away
} catch(WaitTimeoutException e) {
// if spinner loads & deloads faster than this code is reached
// then WTE will be caught and we dont need to handle the spinner any more
//println(e.printStackTrace())
}
Your boolean expression is more complicated than it needs to be, and in this case you might be noting (!) something you don't mean to be.
in general, you never need to compare booleans. (bool1==true) is the same as saying (bool1).
instead of saying
if(!$(".loader").displayed== true){}
just say:
if($(".loader").displayed){} //to check if the div is displayed
or
if(!$(".loader").displayed){} //to check if the div is not displayed
You can try with code if(!$(".loader")==undefined){}

geb StaleElementReferenceException

I have just started using geb with webdriver for automating testing. As I understand it, when I define content on a page, the page element should be looked up each time I invoke a content definition.
//In the content block of SomeModule, which is part of a moduleList on the page:
itemLoaded {
waitFor{ !loading.displayed }
}
loading { $('.loading') }
//in the page definition
moduleItems {index -> moduleList SomeModule, $("#module-list > .item"), index}
//in a test on this page
def item = moduleItems(someIndex)
assert item.itemLoaded
So in this code, I think $('.loading') should be called repeatedly, to find the element on the page by its selector, within the context of the module's base element. Yet I sometimes get a StaleElementReference exception at this point. As far as I can tell, the element does not get removed from the page, but even if it does, that should not produce this exception unless $ is doing some caching behind the scenes, but if that were the case it would cause all sorts of other problems.
Can someone help me understand what's happening here? Why is it possible to get a StaleElementReferenceException while looking up an element? A pointer to relevant documentation or geb source code would be useful as well.
It turns out that the problem was that the reference to the element represented by the module itself had become stale by modification, and not the .loading element. I suspect that the exception originated from that line because it was trying to search within the module's base element to find the .loading element. The solution is to load the module at the same time as checking for the element inside it. In this case it would look something like this:
//In the content block of SomeModule, which is part of a moduleList on the page:
itemLoaded { !loading.displayed }
loading { $('.loading') }
//in the page definition
moduleItems {index -> moduleList SomeModule, $("#module-list > .item"), index}
//in a test on this page
waitFor { moduleItems(someIndex).itemLoaded }
Thanks to Marcin on the geb-user mailing list for pointing me in the right direction.

Chrome WebDriver hungs when currently selected frame closed

I am working on creation of automated test for some Web Application. This application is very complex. In fact it is text editor for specific content. As a part of functionality it has some pop-up frames. You may open this pop-up? make some changes and save them - closing current frame. May problem is in that fact, that close button situated inside frame will be eliminating. And this force Chrome WebDriver to hung. My first try was like this:
driver.findElement(By.xpath("//input[#id='insert']")).click();
driver.switchTo().defaultContent();
But it hungs on first line after executinh click command as this command close frame.
Then I change to this(I have JQuery on the page):
driver.executeScript("$(\"input#insert\").click()");
driver.switchTo().defaultContent();
But this leads to same result.
Then I use this solution:
driver.executeScript("setTimeout(function(){$(\"input#insert\").click()}, 10)");
driver.switchTo().defaultContent();
And it hungs on second line. Only this solution works:
driver.executeScript("setTimeout(function(){$(\"input#insert\").click()}, 100)");
driver.switchTo().defaultContent();
but only if you don't take into account, that it is unstable - some timing issue may occur.
So may question is there more cleaner and more stable way for switch out from closed frame?
P.S.: executeScript - self defined function to decrease amount of code. It simply executer some js on page.
Update:
I realized I was wrong. This problem is not for all iframes. It's occur when tinyMCE popup used. Situation is exactly like in this topic. So it's doubtful I will find answer here, but who knows. Solution described above will help, but only for very short amount of time, meaning that after several seconds pass chromedriver will hangs on next command.
This is how i would do it in Ruby, hopefully you can change it for java
$driver.find_element(:xpath, "//input[#id='insert']").click
$wait.until {$driver.window_handles.size < 2} #this will "explicitly wait" for the window to close
handles = $driver.window_handles #get available window handles
$driver.switch_to.window(handles[0]) #navigate to default in this case the First window handle
hope this helps
Problem was in this line of tinyMCEPopup code:
DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak
Executing this script on page fix hang problem(but possibly creates leaks :) ):
(function() {
var domVar;
if (window.tinymce && window.tinymce.DOM) {
domVar = window.tinymce.DOM
}
else if (window.tinyMCE && window.tinyMCE.DOM) {
domVar = window.tinyMCE.DOM
}
else {
return;
}
var tempVar = domVar.setAttrib;console.log(123)
domVar.setAttrib = function(id, attr, val) {
if (attr == 'src' && typeof(val)== 'string' &&(val + "").trim().match(/javascript\s*:\s*("\s*"|'\s*')/)) {
console.log("Cool");
return;
}
else {
tempVar.apply(this, arguments);
}
}
}());
Bug and solution also described here
Note. Code above should be added to parent frame, not into popup frame.

problem with RegisterClientScriptBlock

i have to run following javascript through one of my method. But its not running
Whats wrong with the code.
private void fillGrid1()
{
GridView1.DataSource = myDocCenter.GetDsWaitingForMe(Session["UserID"].ToString());
HiddenField1.Value = { myDocCenter.GetDsWaitingForMe(Session["UserID"].ToString()).Tables[0].Rows.Count).ToString();
GridView1.DataBind();
String csname1 = "PopupScript1";
String csname2 = "ButtonClickScript1";
Type cstype = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the client script is already registered.
if (!cs.IsClientScriptBlockRegistered(cstype, csname2))
{
StringBuilder cstext2 = new StringBuilder();
cstext2.Append("<script type=\"text/javascript\"> ");
// You can add JavaScript by using "cstext2.Append()".
cstext2.Append("var count = document.getElementById('ctl00_ContentPlaceHolder1_HiddenField2');");
cstext2.Append("var count = '100';");
cstext2.Append("document.getElementById('sp2').innerHTML = count;");
cstext2.Append("script>");
cs.RegisterClientScriptBlock(cstype, csname2, cstext2.ToString(), false);
}
}
Your script tag is not properly closed.
Change
cstext2.Append("script>");
to
cstext2.Append("</script>");
On top of what adamantium said, your JS looks a bit strange. You seem to declare and set the count variable twice - did you mean to do this.
Following that, best thing to do, render the page then view source. is your JS getting rendered to the page? try and stick an alert in there... is it firing?
> cstext2.Append("var count =
> document.getElementById('ctl00_ContentPlaceHolder1_HiddenField2');");
I would use the ClientID property here. HiddenField2.ClientID
RegisterClientScriptBlock emits the script just after the <form> tag openning. Browser executes this script just after the tag openning as well but referenced elements are not processed yet at this time - browser cannot find them.
RegisterStartupScript method emits the script just before the <form> tag ending. Nearly all page elements are processed by the browser at this place and getElementById could find something.
See http://jakub-linhart.blogspot.com/2012/03/script-registration-labyrinth-in-aspnet.html for more details.