How to wait for an animation to complete with watir-webdriver? - watir-webdriver

I have a test scenario which have to click on an element displayed after an animation, but element is not available for action while it is animated: Selenium::WebDriver::Error::UnknownError: Element is not clickable at point (...).
Is there a way to synchronize on the animation completion to have deterministic behavior (I will avoid sleep-based solutions).

We found a solution to that: in fact, we use Tweeter Bootstrap, and animations are realized through CSS properties.
The "better" way to get out of this was to wait until CSS property had its final value.
Watir::Wait.until {
top = browser.execute_script 'return $("#my-id").css("top");'
top == "30%"
}
Any "yet better" idea is welcome.

Related

What is the best css selector for 'all children'?

On my page - in my css I have put:
*{pointer-events:none;}
.pev{pointer-events:auto}
This is because I want a strong ui and there are some draggable things i don't want users accidentally selecting things, etc
So I am taking away all clicks,hovers etc and just putting them back on things that need to be touched
i have an element (classed .play) that holds a youtube player (given it's parent the prev class and jquery draggable).
I would like to know the proper most efficient way to bypass .prev and * and just add pointer-events auto to the player and anything inside it via inheritance (I think this is correct)
Which of these is better syntax?
.play*{pointer-events:auto;}
.play < *{pointer-events:auto;}
UPDATE----------------------------
Thanks to Pinal, I have been able to stabilize the pointer-events (if the cursor happens to interfere with the video when dragging the pointer events of the video would normally stop the drag event eg the mouse moves faster than the dragged element then a stall in dragging will happen.. Result === UI looks broken).
so here is the simple fix (thanks again man)...
css:
*{outline:none;pointer-events:none;}
.pev{pointer-events:auto!important;}
.play > * {pointer-events:auto;}
.playdrag > * {pointer-events:none!important;}
jquery:
$(document.body)
.on('mouseover','.play',function(){
$('.play').draggable({ containment:'#screensize',scroll:false});
})
.on('mousedown','.play',function(){
$(this).addClass('playdrag');
})
.on('mouseup','.play',function(){
$(this).removeClass('playdrag');
});
So very cool, makes everything smooooooooth!
You have misprints, you forgot about spaces and children selector is >, not <:
.play * {pointer-events:auto;}//select all inside
.play > *{pointer-events:auto;}//select children only
So better use .play > * for only children selection.

EffectQueue and chaining effects in IceFaces 1.8

I'm currently working with IceFaces 1.8, and have been trying to find an simple way to chain effects on UI Components. For example, I have a "Show Help" link at the top right of the page. When clicked, help text will appear below certain controls for users. I'd like this text to appear by sliding down, then highlighting.
I have a basic isRenderHelp() method on my bean that returns true or false, and use that to render effects using the fire attribute on the <ice:effect> tag, so it looks something like this:
<ice:effect effectType="slidedown" fire="#{myBean.renderHelp}">
<ice:effect effectType="slideup" fire="#{!myBean.renderHelp}">
This works causing the help section to slide in and out as the help link toggles the renderHelp flag in the bean. There is the small exception that renderHelp returns null before the link is clicked for the first time to prevent the slideup animation from firing on the first page render.
Now, I noticed looking through the showcase code for 1.8 that there is an EffectQueue class that extends Effect. This allows me to add mutliple Effects to the queue in my bean, and return the queue from a getEffect method that I can then assign to a panelGroup effect attribute. However, it does not execute the events in the queue, despite having their priorities set. I'm sure I'm not using it properly, and I'm wondering how it should be used.
Normally I'd use jQuery for this type of thing, but the UI uses many partial submits. Our page is displayed via a Liferay portlet, so on any partialSubmit the view is rerendered, undoing any modifications to the DOM by jQuery.
So is there any simple way to chain effects in IceFaces 1.8? Suggestions?
here is how I implemented the effectQueue to appear and fade the text.
private EffectQueue effectQueue;
public Effect getSaveSettingsEffect() {
return effectQueue;
}
public void fireEffect(ActionListener e) {
if(effectQueue == null) {
effectQueue = new EffectQueue("apperAndFade");
Appear appear = new Appear();
appear.setDuration(2);
effectQueue.add(appear);
Fade fade = new Fade();
fade.setDuration(3);
effectQueue.add(fade);
effectQueue.setTransitory(true);
}
effectQueue.setFired(false);
}
facelet:
<ice:commandButton value="fireEffect" action="#{bean.fireEffect}"/>
<ice:outputText value="text" style="display: none;" effect="#{bean.effectQueue}"/>

QCompleter and Tab key

I'm trying to make a Completion when pressing tab, you get the first completion of all possibilities.
But, in a QWidget-based main window, pressing tab will make that QLineEdit lost focus, and completion popup hides after that.
Is there a way to fix it ?
Have you tried to subclass QLineEdit and intercept the key press event?
Alternatively you could set up an event filter.
Whew. It took me some time to figure this out :) Multiple times I have tried to solve this problem, but always gave up. Now, I dug enough to find the answer.
OP, please pardon me, because the code here is Python, but should be understandable and work for C++ as well.
Basically, the problem I had was "how to select an entry in the QCompleter"; I didn't notice before, but the answer is in the popup() method. QCompleter works with a model and a view, which contains the things to show.
You can change the current row as you wish, then get the index of that row in the model, then select it in the pop-up.
In my code, I subclassed QLineEdit, created a tabPressed signal which is emitted every time Tab is pressed. Then, connected this signal to a method of the same class which does this:
get the current index;
select the index in the popup;
advance to the next row.
As implementation, this is very trivial, but for my current purpose this is enough. Here's the skeleton (just for the tab part, it's missing the model and everything else).
class MyLineEdit(QLineEdit):
tabPressed = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self._compl = QCompleter()
self.tabPressed.connect(self.next_completion)
def next_completion(self):
index = self._compl.currentIndex()
self._compl.popup().setCurrentIndex(index)
start = self._compl.currentRow()
if not self._compl.setCurrentRow(start + 1):
self._compl.setCurrentRow(0)
def event(self, event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
self.tabPressed.emit()
return True
return super().event(event)
You may need to adjust/fix few things, but this is the basic idea.
EDIT:
For details see
http://www.qtcentre.org/threads/23518-How-to-change-completion-rule-of-QCompleter
There's a little issue: when Return is pressed, the things don't work properly. Maybe you can find a solution to this problem in the link above, or in the referenced resources therein. I'll fix this in the next few days and update this answer.
There is probably a better solution but one that comes to mind is to change the focus policy for all other widgets on the form to something that doesn't include "tab" focus. The only options that don't use the tab key are Qt::ClickFocus and Qt::NoFocus.

Redrawing control behind composite with SWT.NO_BACKGROUND

Original goal:
I have a TreeMenu that i use to display my Menu.
In this tree, a user can select different items.
I would like to disable the tree, so that a user cannot select a new item after choosing the first.
The catch is, we cannot use setEnabled, because we are not allowed to use the greyed out look. The look/colors may not change.
Our proposed solution
Our first idea was to use a Composite with SWT.NO_BACKGROUND on top of the menu, to prevent any user interaction with the TreeMenu.
Code:
final Composite cover = new Composite(getPage().shell, SWT.NO_BACKGROUND);
cover.setLocation(getMenu().getLocation());
cover.setSize(getMenu().getSize());
cover.moveAbove(getMenu());
This has a problem with redrawing.
If the screen is covered by another screen and then brought back to front, the Cover Composite is filled with fragments of the previous overlapping window.
Our idea was to manually redraw the menu:
cover.moveBelow(getMenu());
getMenu().update();
cover.moveAbove(getMenu());
We placed the code inside the paintEventListener.
But this caused an infinite loop and did not solve the problem.
Questions
Does anyone have an idea how we can achive our orignial goal?
Does anyone know how we can make our proposed solution work?
Look at SWT-Snippet80. It shows how to prevent selections. A solution to your problem would be adding a listener like this to your tree:
tree.addListener(SWT.Selection, new Listener() {
TreeItem[] oldSelection = null;
public void handleEvent( Event e ) {
Tree tree = (Tree)(e.widget);
TreeItem[] selection = tree.getSelection();
if ( oldSelection != null )
tree.setSelection(oldSelection);
else
oldSelection = selection;
}
});
I wouldn't recommend trying to implement your workaround. I believe that placing transparent controls on top of each other is unsupported in SWT - I think I read a comment from Steve Northover on this subject once. Even if you made it work for some OS, it probably won't work in another - it's too much of a hack.
A solution that is supported by SWT, is having transparent windows on top of each other. But that is also really hard to implement (resizing, moving, always on top, redraw artifacts) and probably as big a hack as the other workaround. Go for the listener.

GTK detecting window resize from the user

In GTK (or pygtk or gtkmm...)
How can I detect that an application window has been manually resized by the user, as is typically done by dragging the window's edge?
I need to find a way to differentiate manual resizes from resizes that originate from gtk, such as changes in window content.
Have you tried connecting to the GDK_CONFIGURE event?
Check out this example under the
"Moving window" section. The example shows a callback doing something when the window is moved, but the configure event is a catch-all for moving, resizing and stack order events.
I managed to pull this off by watching for size_allocate and size_request signals on the GtkWindow. If size_request ever got smaller, I called resize(1,1). If size_allocate was ever bigger than expected, I turned the system off.
One thing I made sure to handle was size_request returning big, then small, and having size_allocate be big and then small. I don't know if this is possible, but I fixed it by making sure to only decrease the expected values for size_allocate when I got a smaller size_allocate, not when I got a smaller size_request.
Make sure that your size_request handler comes after the base class' handler so that you get the right values. I did this by overriding the method and then calling the base class method first.
I've tried this in both 1 and 2 dimensions and it seems to work either way.
In my case I was trying to distinguish between a user resizing a Gtk.Paned from the user resizing the whole window. Both emitted the notify::position signal.
My solution was, since I can't know if the user is resizing the window from the widget, reverse what I wanted to know. Record if the user has re-positioned the widget and ignore updates if the user didn't initiate them on my widget.
That is to say, instead of testing "if window being resized" I recorded the button-press-event and button-release-event's locally so I could instead test "if widget being re-positioned"
from gi.repository import Gtk
class MyPaned(Gtk.Paned):
_user_activated = False
def on_position(self, _, gparamspec):
if self._user_activated:
# widget touched
else:
# window resized (probably)
def on_button_press(self, *_):
self._user_activated = True
def on_button_release(self, *_):
self._user_activated = False
dev __init__(self, *args):
super(MyPaned, self).__init__(*args)
self.connect('notify::position', self.on_position)
self.connect('button-press-event', self.on_button_press)
self.connect('button-release-event', self.on_button_release)
Effectively by recorded when the user started and ended interacting with my widget directly, I could assume the rest of the time was due to the window being resized. (Until I find more cases)
In PyGTK, I've always watched for the expose_event for a window resize, then use the get_allocation method to get the new size.
You may be able to throw something together by using gdk_window_get_root_origin to get the top left corner of the window and gdk_window_get_geometry to get the width and height. Then you could hook a callback into the GDK_BUTTON_PRESS_MASK and check to see if the button press occurs near/on one of the edges of the window.
Of course, this seems quite hackish and it really bothers me that I couldn't find some simple way in the documentation for GdkWindow to do this. There is a gdk_window_begin_resize_drag function which really makes me think there's a cleaner way to do this, but I didn't see anything more obvious than my answer.