Assert element no longer present - webdriver

Using webdriver and testing an application built using gwt. I want to first assert that an element becomes present. This element is loaded dynamically and it is not trivial to test. However I need to assert that the element becomes no longer present. As in it is no longer present in the dom. My original approach to this is to build an ExpectedCondition and then wait for the condition i.e.
ExpectedCondition<Boolean> e = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.findElements(By.cssSelector(someCSSpath)).size() == 0;
}};
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(e);
I would have expected that would have waited for 15 seconds for the element to disappear from the dom, I would expected that it would poll every 500 milis. I would expect that at every poll the bool would be false as the element would be found until such time as it disappears and at which point the condition becomes true. What I find in my output is that indeed it polls every 500 milis however once the condition becomes true I actually wait for an entire minute before moving onto the next step. This seems incorrect behavior, am I missing something? Any suggestions?

Try to use : ExpectedConditions.stalenessOf(..) as to check that the element was successfully removed from DOM. Works for me.

Did you set "implicitlyWait" to 60 seconds?
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
When object disappears it will wait on "findElements" method 60 seconds before it returns.
I recommend to set "implicitlyWait" to 0 before running "wait.until(e);" method and then set it back to 60 seconds.

If you got a handle on WebElement you can use this.
new WebDriverWait(driver, 2).until(ExpectedConditions.stalenessOf( webElement ));

Related

Qt measuring rendering time during which application is frozen

I have a Qt application, where, among other things, there is a function render which goes through a list of objects and creates for each an according (subclassed) QGraphicsPathItem which it then puts as a child in a (subclassed) QGraphicsScene. (It is done in the code below through a visitor GGObjConstructor which gets initialized with the variable scene which is the scene where the items are to be added to).
XTimer timer;
timer.start();
gobjlist gobjlis = ogc._gobjectlis;
GGObjConstructor ggoc(scene, z_value, bkground_color);
for(auto obj: gobjlis) {
obj->exec( &ggoc );
}
timer.stop();
My class XTimer is used in an obvious way to measure the time for this proceeding.
Now the problem is: Only the time spent in the loop where all the items are prepared and inserted into the scene is measured by timer. For a typical example with ~165000 items this gives about 7.5 sec as timer-value at reaching timer.stop(). But the application is after these 7.5 sec still frozen, with the screen-window where the scene is to by displayed yet invisible and only after about 25 sec (hand-stopped) suddenly the display window appears with all the items to be displayed.
Now of course I would like to measure these "freeze time" (or time till the application becomes responsive again, or maybe time till display window appears). But I found no way to do this although I looked some time through stackoverflow or the net in general. The best hint I found was
stackoverflow question
The answer there seemed to imply, that it would be not really simple to achieve (overriding paintEvent method and such things).
Question: Is this true? Or is there a simple way to measure the time till the application becomes responsive again/the image is really displayed?
I had a similar problem with an application once, where I wanted to measure the time the app freezes to figure out with logging what was causing these freezes. What I came up was to measure how long the Eventloop of the mainthread was not responding, because this directly corresponds to a frozen app.
The basic idea is to not run a QApplication but inherit from QApplication and override the notify() function. Some apps do this anyway to catch exceptions which would otherwise break the eventloop. Here is some pseudo-code which should bring the idea across:
bool MyApplication::notify( QObject * receiver, QEvent * event )
{
// something like storing current time like:
// auto start = std::chrono::system_clock::now();
// auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(start - end );
// if( elapsed.count() > 1000 ){
// log something like: Mainthread responds again after <elapsed> seconds
// }
// Note that end must be a member variable
// end = start;
return QApplication::notify(receiver, event);
}
Note 1: If your app does not continuesly run through notify() you can for testing purposes introduce a dummy QTimer which triggers faster than the logging time threshold.
Note 2: if you use multiple threads, esp. QThreads it could be necessary to filter the receiver object and perform that code only if the reciever is in the mainthread.
With this code you can log every freeze of the main-thread (frozen GUI) and determine the length of the freeze. With proper logging you can figure out whats causing the freezes.
Keep in mind that this will only log after the freeze has resolved!
Addition:
It is more complicated and slow, but for debugging/investigation purposes you can store the last event and Object-Tree of the reciever and log that as well. Than you even know which was the last event which triggered the freeze and the recieving Object.

Process Codes in the Middle of a SequentialTransition- JavaFX

I am trying to execute a SequentialTransition, but between the animations, I need to execute some commands.
My problem is that it is always executing the last commands passed on the node. Is there any way to fix this?
Where is "is ignored" is the code that I need to be executed in the first animation, then where this "is executed" is the code that I need to be executed in the second animation.
Thanks
private void startAnimation(){
vb_adv.setPrefWidth(197);
ap_services.toBack();// Is ignored
vb_adv.toFront();// Is ignored
ScaleTransition expandAdvertising = new ScaleTransition(Duration.millis(2000), vb_adv);
expandAdvertising.setToX(2);
expandAdvertising.setCycleCount(2);
expandAdvertising.setAutoReverse(true);
ap_services.setPrefWidth(124);
ap_services.toFront();//is executed
ScaleTransition expandService = new ScaleTransition(Duration.millis(2000), ap_services);
expandService.setDelay(Duration.seconds(3));
expandService.setToX(3.7);
expandService.setCycleCount(2);
expandService.setAutoReverse(true);
SequentialTransition sequence = new SequentialTransition(expandAdvertising, expandService);
sequence.play();
}
In the code as you currently have it, you move ap_services to the back of the z-order, and vb_adv to the front:
ap_services.toBack();
vb_adv.toFront();
Then you create and set up you ScaleTransition. Note that doing this part takes essentially no time; all you are doing is configuring the animation which will run later.
The next thing you do is to move ap_services to the front:
ap_services.toFront();
Note that this will happen essentially immediately after the previous calls to toFront() and toBack(), and of course this negates the effect of those calls. So your initial calls are actually executed (not "ignored"), but you immediately do something which undoes their effect.
What you really want is to execute ap_services.toFront() after the ScaleTransition finishes. You can do this by putting that call in an onFinished() handler:
// ap_services.toFront();
expandAdvertising.setOnFinished(e -> ap_services.toFront());

QTableView not updating properly

I am creating a small program that takes user input into a model and then shows that input in several views that take it through filters.
When the user clicks the button that accepts the input, the program updates the amount of cells in the views and then resizes those cells as necessary so that they fit neatly in their area.
My problem is that the cell resizing doesn't seem to work for one of the views for some reason (I tried looking for differences but couldn't find a reason for what I'm experiencing).
I'm calling the cell resizing function in two places:
dataChanged slot.
resizeEvent slot.
If the cell resize function gets called twice inside dataChanged, then the view does update, however this involves some calculations and ui access and obviously not supposed to happen.
If I resize my window then the cells are resized properly.
I suspect that I'm always one update behind - that the view doesn't paint until the new update starts getting calculated and then that new update is on hold until the next calculation (since resize happens a lot of times in succession it might just act the same as the button but is harder/impossible to notice).
I have some dirty workarounds:
As I mentioned, if I call my cell resize function again, the view updates properly.
If I remove the second "if" in this next piece of code then everything works.
I thought I'd save my computer some work by only processing when the entire input had been received. My thinking was that, although dataChanged is emitted for every single item I'm inserting, I only really need to update once it is all in:
void MainWindow::on_dataChanged()
{
static int left_to_insert = -1;
if ( 0 > left_to_insert )
{
left_to_insert = m_model.rowCount() - 1;
}
if ( 0 == left_to_insert )
{
...
m_matrix_proxy.resize_to_fit();
adjust_matrix_cells_sizes();
}
--left_to_insert
}
Is it bad to only process the last signal? Why?
I tried calling update() and/or repaint() on both the matrix and the main window.
I tried calling both of these on the viewport of the QTableView and tried calling them in succession from the matrix itself to the highest parent that didn't make my program crash. (ui->matrix->parentWidget()->parentWidget()...)
I tried qApp->processEvents().
I even resorted to emitting a resizeEvent, but this is overkill IMO as it makes some calculations be performed again.
Just in case it is somehow relevant: The data appears correctly. The only thing that's wrong is that the cells don't resize.
You need to emit layoutChanged signal from your model. But be care with large amounts of items, because handling of this signal may take a lot of time.
Similar questions: one, two
This logic in only code sample you have given is wrong. And this static keyword makes it even worse.
Actual answer:
There is ready solution delivered by Qt! See documentation of QHeaderView::ResizeMode and QHeaderView::setSectionResizeMode
Old answer:
IMO this should look like this:
void MainWindow::MainWindow()
…
{
…
mNeetToResizeCells = false;
connect(this, &MainWindow::NeedUpdateCellsSizes,
this, &MainWindow::ResizeTableCells,
Qt::QueuedConnection); // this is imporatant
}
void MainWindow::on_dataChanged()
{
if (!mNeetToResizeCells) {
mNeetToResizeCells = true;
emit NeedUpdateCellsSizes();
}
}
void MainWindow::ResizeTableCells()
{
mNeetToResizeCells = false;
// update cells sizes here
ui->tableView->resizeColumnsToContents();
ui->tableView->resizeRowsToContents();
}
This way all data updates performed in one iteration of event loop will cause only one invocation of MainWindow::ResizeTableCells in some future iteration of event loop.

Moving to the bottom of an element with Webdriver.io

I have a page that has elements that become visible as you scroll down. I am trying to execute a test to make sure the elements are not there until the scroll is to the bottom of the elements, but I can't seem to figure out how to pass the size from one call (elementIdSize()) to the scroll offset of the next call (scroll()). Admittedly my brain does not yet get the concept of "promises" past simple call chaining.
I tried something like this:
this.browser
.setViewportSize({width: 1000, height: 600})
.element(selector)
.then(function(e) {
console.log('then element: ', e);
element = e;
})
.elementIdSize(element.id)
.then(function(size) {
console.log('Size: ', size);
})
.call(callback);
Which I was hoping would use the passed-in selector to get the element, set the element in the then(), then call elementIdSize() on the element's ID, but the var element is never set from the element() call, and the objects I am getting back don't seem to be what I am trying to get anyway. I feel this is some simple piece of knowledge I am missing here that will make all this "click".
I am using the APIs here for looking up the Webdriver calls, but the documentation doesn't give much details.
It's important to understand that all parameters will get resolved once you execute the chain. That means you can't change them anymore once you've executed the first command basically. In your example you set the value of the element variable in a promise callback. At the time you do that, elementIdSize already read the element variable (and probably threw an error).
The proper way to this is to execute commands that have arguments which get resolved at a later time in then or finish routines. You can also save commands in WebdriverIO by using action commands instead of raw protocol commands. So just use getSize instead of call element first and then call elementIdSize. That is the job of getSize ;-)
I am not sure what exactly you try to do but here is the code that should do the trick:
this.browser
.setViewportSize({width: 1000, height: 600})
.getElementSize(selector).then(function(size) {
console.log('size of element "' + selector + " is', size);
// now as we have the size execute the scroll in a then callback
return this.scroll(0, 600 + size.height);
})
// this get executed once we we did the scrolling since
// the getSize promise is only then fulfilled once the promise
// within the then function is resolved
.isVisible(otherElem).should.be.eventually.be(true, 'element was visible after scrolling')
.call(callback);
(As a side note: we already working on WebdriverIO v4 that will allow to execute commands synchronously, so no more promise headaches ;-))

How to remove (not replace) a fragment present in FrameLayout?

I have the ID of a FrameLayout which hosts different fragments (identified by different tags) at any given time. I sometimes wish to remove (not replace) whatever fragment is currently in the FrameLayout container. Here is what I tried and did not work:
Fragment f = fm.findFragmentById(R.id.framelayout_container);
if (f != null) {
txn.remove(f);
}
txn.commit();
So, I'm passing the ID of the container and if anything comes back (I was expecting a fragment currently in the container) I want to remove it.
Problem is that when I call above again (another UI event like button click), the findFragmentById returns the exact same Fragment again, as if prior remove/commit didn't do anything.
Btw, replace() works fine -- I'm struggling with the remove() only.
After spending more time on above problem, I discovered that calling remove() doesn't actually remove the fragment from the FragmentManager (duh) -- i.e. subsequent calls to findFragmentById still return the original fragment. What remove() does to the fragment is it changes its "isAdded" state, specifically:
fragment.isAdded() returns false
fragment.isDetached() returns false
fragment.isInLayout() returns false
fragment.isHidden() returns false
(jeez, haven't they exhausted all verbs by now?)
I expected the fragment to be actually removed from the manager after calling remove(), sort of like removing a node from a DOM tree. Silly me.

Resources