WaitCell and object does not exist
SOLVED- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
WaitCell and object does not exist
Afternoon folks,
I'm running into an intermittent issue I hope have you have ideas about. There are loads of questions that are ALMOST the same, but none of them seem to be quite what I'm experiencing. Short summary: if I use WaitCell, very occasionally the WaitCell call itself causes "The object "Cell(0,0) does not exist" error. The test will continue running, but because there's an error, the test is marked as failed.
the code:
grid.RefreshMappingInfo(); // I can sort the grid, so need to refresh the mapping just in case, else the mappings will be broken var waitCell = grid.WaitCell(0,0,10000); //The object doesn't exist and is output to the error about 0.5 seconds after the call
grid.FindChildEx(… //this works again
I'm using it as a way to confirm that RefreshMappingInfo()has completed before I try and use Find methods again. At worst it should return a stub, right ?
-------------------------------------------------
Standard syntax disclaimers apply
Regards,
Solved! Go to Solution.
- Labels:
-
Name Mapping
-
Object Recognition
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Right, brace yourself. This isn't 100% the same and leaves out a lot of code for the sake of brevity. Also, there might be some syntax errors, but hopefully it shows the general idea
function DoStuff(Grid) //where Grid is an aliased object { var theGrid = GridTableObject(Grid).Fetch(); theGrid.Sort("ID"); Delay(2000,"Give Grid time to sort"); theGrid.ClickButtonInACell(2,4); } function GridTableObject(Grid)
{
/*Grid is a mapped table
Structure : Grid(table) -> cell(0,0)->
Table(there are multiple tables in this Cell) -> cells
*/
if (!(this instanceof GridTableObject))
{
return new GridTableObject(Grid);
}
if(Grid==undefined)
{
Log.Error("GridTable object has no Aliased Parent specified.","",pmNormal,"","");
}
var grid = Grid;
var gridTable = null;
var gridTableName = null;
var rowHeaderCellCollection = [];
_setGridTable();
function _setGridTable()
{
//Always refresh mapping info. A click can always happen after a sort
_resetStuff();
grid.WaitProperty('Exists', true, 10000);
var waitCell = WaitRapper("Cell",grid,[0,0]);
/*this isn't the first time we are setting the gridTable,
so we know what it's called and can wait for it to load
*/
if(gridTableName!=null)
{
var waitTable = WaitRapper("Table", waitCell, gridTableName);
}
var gridTables = grid.FindAllChildren(props,values,3).toArray();
if(gridTables.length>0)
{
for (i = 0; i < gridTables.length; i++)
{
if(gridTables[i].onClick != null && gridTables[i].onClick != "")
{
gridTable = gridTables[i];
break;
}
}
if(gridTable == null || !gridTable.Exists)
{
Log.Error("Unable to find Table element of Grid [" + grid.MappedName + "]","", pmNormal, "", (grid!= null && grid.Exists) ? grid : "");
}
else
{
gridTableName = gridTable.ObjectIdentifier;
}
}
else
{
Log.Error("Unable to find Table element of Grid [" + grid.MappedName + "]","", pmNormal, "", (grid!= null && grid.Exists) ? grid : "");
}
}
function _populateHeaderCells()
{
if(rowHeaderCellCollection!=null && rowHeaderCellCollection.length>0)
return;
var props = ["ObjectType","RowIndex"];
var values = ["Cell",0];
var cellElements = gridTable.FindAllChildren(props,values,1).toArray();
for (i=cellElements.length-1;i>=0;i--)
{
rowHeaderCellCollection.push([cellElements[i],cellElements[i].ColumnIndex,cellElements[i].Visible,cellElements[i].Name,cellElements[i].contentText]);
}
}
this.Sort = function(columnName)
{
//where columnname matches with the text found in an as yet to be determined cell which as contentText of "columnName" in first visible row
if(StringIsNullOrEmpty(columnName))
{
Log.Error("No column name specified to sort on.","", pmNormal, "", (grid!= null && grid.Exists) ? grid : "");
return;
}
_setGridTable();
_populateHeaderCells();
for(i=0;i<=rowHeaderCellCollection.length;i++)
{
if(aqString.ToUpper(rowHeaderCellCollection[i][4]) == columnUpper)
{
headerCell = rowHeaderCellCollection[i][0];
break;
}
}
if(headerCell.Exists)
{
headerCell.Click();
}
else
{
//Log an error
}
}
this.ClickButtonInACell = function(RowIndex,ColumnIndex) //This isn't quite what it does, buts a close proxy/shorthand - This button can move if you sort
{
_setGridTable();
var collectionofbuttons = [];
var buttonProps = ["contentText","tagName", "Visible"];
var buttonValues = [buttonText,"DIV", true];
//some intermediate code to get all the cells in a row - useful if you need to do more than just click the button. e.g. test the label in cell 3 is '2.7'
var buttonElements = rowCellCollection[ColumnIndex].FindAllChildren(buttonProps, buttonValues,100).toArray();
if(buttonElements.length==0)
{
Log.Error("Unable to find [" + buttonText + "] button in Grid [" + grid.MappedName + "]","", pmNormal, "", (grid!= null && grid.Exists) ? grid : "");
return false;
}
else
{
var buttonElement = buttonElements[0];
if(buttonElement != null && buttonElement.Exists)
{
buttonElement.Click();
}
else
{
Log.Error("Unable to find [" + buttonText + "] button in Grid [" + grid.MappedName + "]","", pmNormal, "", (grid!= null && grid.Exists) ? grid : "");
return false;
}
}
}
this.Fetch = function()
{
return this;
}
}
I haven't experienced any issues since adding
_resetStuff();
grid.WaitProperty('Exists', true, 10000); var waitCell = WaitRapper("Cell",grid,[0,0]); if(gridTableName!=null) //this isn't the first time we are setting the gridTable, so we know what it's called and can wait for it to load { var waitTable = WaitRapper("Table", waitCell, gridTableName); }
but I haven't really been testing either
-------------------------------------------------
Standard syntax disclaimers apply
Regards,
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
> I didn't think a mapping info refresh would cause an object to actually stop existing
Exactly so:
-- Mapping refresh (probably) does not invalidate the programming object referenced by the grid variable while the 'physical' object on the page might be recreated;
-- As test code calls .FindChild() method of the aliased grid object, this causes TestComplete to refresh the parent object (i.e. grid). If the grid happens to be not recreated completely, refresh fails and subsequently does the call to .WaitCell().
Here is the article I had in mind when wrote this and my initial replies: https://support.smartbear.com/testcomplete/docs/reference/test-objects/members/common-for-all/refres...
/Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Edit: clarified code.
Well, after extensive testing I can say that the issue is gone. The changes I made as a result of this thread has both made my scripts faster and more reliable - thanks It didn't resolve the majority of the issues though. I finally found what is causing the majority of the errors and it has nothing to do with this. The problem lies with this piece of code that posts an image of a parent of the tested object because sometimes just seeing a blank textbox doesn't mean anything:
WriteAnEntry(Aliases.browser...MyTextBox,"I'm writing to the textbox",3); function WriteAnEntry(aliasObj,messageText,addPicture,moveXTiersUpforPicture) { if(aliasObj===null || aliasObj==undefined || !aliasObj.Exists) { Log.Message(messageText); return; } var imageobject = aliasobject; var currenTier = 0 if(addPicture) { while(imageobject!=null && imageobject!=undefined&¤Tier<moveXTiersUpforPicture) { if(imageobject.ObjectType!="Form") //Don't go TOO high' break; currenTier++; if(imageobject.Parent !=null && imageobject.Parent !=undefined && imageobject.Parent.Exists) { imageobject = imageobject.Parent; } } }
var testtheobject = imageobject!=null && imageobject!=undefined&& imageobject.Exists;
//testtheobject is true now //nowhere in the above code do I ever allocate a null/undefined/!exists to my imageobject var //but, very occasionally when I do the following call, the image object is gone, //so it's the testing for null or undefined causes the error Log.Message(messageText,"", pmNormal, "",(addPicture && imageobject!=null && imageobject!=undefined ) ? imageobject:""); }
So, how did I fix it ? Try.. Catch
var canDoImage = null; var placeholderObj = null; try { placeholderObj = (imageobj!=null && imageobj!=undefined && imageobj.Exists) ? imageobj : null; if(placeholderObj==null) { canDoImage = false; } } catch (e) { canDoImage = false; } Log.Message(messageText,"", pmNormal, "",(canDoImage && placeholderObj!=null ) ? placeholderObj:null);
I have NO idea how that object gets lost, but there you have it...
-------------------------------------------------
Standard syntax disclaimers apply
Regards,
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Kudos all round ! No answer was a specific solution, but all of the answers got me closer to the answer in the end and I now have a much better, more stable script
-------------------------------------------------
Standard syntax disclaimers apply
Regards,
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
> piece of code that posts an image of a parent of the tested object
My personal preference is to post an image of the whole web page - this is simpler, more reliable and sometimes may provide you with even better understanding of what went wrong with the test:
if(addPicture) Log.Message(messageText,"", pmNormal, null, Aliases.browser.page.PagePicture());
Note: I am not sure if it is correct to pass an empty string instead of the Picture object like it is in your code. I would pass null instead of the empty string:
Log.Message(messageText,"", pmNormal, null,(addPicture && imageobject!=null && imageobject!=undefined ) ? imageobject:null);
> I have NO idea how that object gets lost,
Again, just a wild guess as I don't know your tested application:
The reason may be the same: the code finds parent of some object, but by the moment of taking a snapshot, the object and its parent are invalidated and destroyed because of page DOM been altered (by some script on the page). Note, that your code takes a snapshot of the parent object not immediately after finding it, but after some time. And this increases the chances of the parent object to be destroyed before the snapshot has been taken.
One more reason to post an image of the page, but not of some container within it. 🙂
P.S.
And one more note:
> addPicture && imageobject!=null && imageobject!=undefined
If the imageobject is found by the means of TestComplete but not via DOM native means (e.g. via XPath), the search result will always be an object with at least the .Exists property. (See https://support.smartbear.com/testcomplete/docs/reference/program-objects/utils/createstubobject.htm... for more details.) This means that instead of the current verification (which is natural for regular developers:) ), you must use this one:
addPicture && imageobject.Exists
The above is one of the several reasons of why search by XPath is highly not recommended in the TestComplete world...
/Alex [Community Hero]
____
[Community Heroes] are not employed by SmartBear Software but
are just volunteers who have some experience with the tools by SmartBear Software
and a desire to help others. Posts made by [Community Heroes]
may differ from the official policies of SmartBear Software and should be treated
as the own private opinion of their authors and under no circumstances as an
official answer from SmartBear Software.
The [Community Hero] signature is used with permission by SmartBear Software.
https://community.smartbear.com/t5/custom/page/page-id/hall-of-fame
================================
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My personal preference is to post an image of the whole web page - this is simpler, more reliable and sometimes may provide you with even better understanding of what went wrong with the test:
I wasn't aware of the PagePicture() method - Much better
Note: I am not sure is it correct to pass an empty string instead of the Picture object like it is in your code. I would pass null instead of the empty string:
It's what TC generated when I converted my KWT to script, so I guess it's OK by them. /shrug
-------------------------------------------------
Standard syntax disclaimers apply
Regards,

- « Previous
-
- 1
- 2
- Next »
- « Previous
-
- 1
- 2
- Next »