Removing events in Shoes - ruby

The is any way to remove the events in Shoes? I searched around many websites and references but I can't found any way to remove a event... I minding that I will need to create my own event manager... its really nescessary? or there is a way to desattach event listeners?

I have found that Shoes only allows a single listener method on a given event, so you can remove a previous listener by calling the event and not passing a block to it.
For example, this Shoes app will clear the click event after it is clicked one time. If you remove the call to click inside the block, then it will fire repeatedly.
Shoes.app
#p = para "Empty"
#click_count = 0
click do |b,x,y|
#click_count += 1
#p.replace "Clicked #{#click_count} time(s)."
click # remove the click handler
end
end

Which keybindings do you want to remove? All events on the Shoes app or just the default bindings?
If you want to override bindings reserved for shoes like "alt-/", "alt-.", "alt-?", paste the following code into the file which contains your application code
class Shoes::App
def Shoes.show_log # gets called on alt-/
end
def Shoes.show_manual # gets called on alt-?
end
def Shoes.show_selector # gets called on alt-.
end
end
The above code monkey-patches the shoes code and in-turn does nothing when the corresponding keys are pressed.
You can use the same technique for rest of the default bindings. grep the shoes source for the key bindings, find the corresponding method and define an empty method within your app to override the built-in method.

Have you tried method.unbind(obj)?

Can you clarify what you mean by "remove a event"? Are you wanting to ignore a specific event or are you wanting to "turn off" an event listener?
If the former, I'd suggest writing a listener that just ignore the event.
If the later, why not make the body of the listener conditional on some externally accessible value, giving yourself an on/off switch.
If you are wanting something else, edit the question to clarify and I'll stop back later and edit my answer.
In response to your comment, I'd re-suggest the second of the above alternatives. If you wanted to get really fancy you could write something like this:
$keypress_listeners = {}
keypress do |key|
$keypress_listeners.values.each { |l| l.call(key)
end
$keypress_listeners[:hero_controller] = lambda { |key| ... }
:
:
$keypress_listeners.delete[:hero_controller]
and likewise for any other events, but that is probably overkill. On the other hand, it would give you total control of the event processing.

Related

Capybara wait until button is enabled?

Surprised I actually haven't come across this, but I have a simple button that is disabled until a dropdown is selected. Sometimes the page isn't fast enough to "enable" the button to be clicked on after the previous dropdown is selected causing it to fail.
I could throw in a "sleep" of a second or two and fix this, but that seems like a lazy/poor way to do this.
Is there a way in capybara (or purely selenium) that I can make it wait until the button is actually enabled? I'd like to throw this is the page model method for this button (as im trying to avoid API specific methods/selenium/etc... in the actual test specs (Although I can if I need to).
FWIW this is specifically for Ruby's capybara framework but pure selenium is fine as well.
Assuming the button you're referring to is actually a button (<button> element, or <input> element with type submit, reset, image, or button) then Capybaras :button selector will (by default) wait for it to be non-disabled.
click_button('Something')
or
find_button('button_id').click
or
find(:button, 'button_value').click
If any of the finder or action methods aren't waiting long enough for a specific element you can always increase the maximum wait time for a specific finder/action by passing a :wait option
find(:button, 'Something', wait: 10).click
If you're not using selector types (if not, why not) and instead are just using raw CSS to locate the element then you can use the :enabled pseudo class along with your existing CSS and something like
find('#my_button:enabled', wait: 10).click
If the element you're calling a button isn't actually a button but some other type of element (<a> etc) styled to look like a button, then you'll need to explain exactly how you're disabling the "button".
In Python you can do something like this:
def wait_until_clickable(driver, xpath, timeout = 1):
while timeout > 0:
try:
element = driver.find_element_by_xpath(xpath)
element.click()
return element
except:
time.sleep(0.1)
timeout = timeout - 0.1
return False

Check if an element with varying text casing is displayed in Appium and perform logic accordingly

I'm using Appium with the Cucumber Framework and utilizing the Ruby language.
My scenario is my app has multiple buttons that I want to call with a single Gherkin statement "I press the "*" button" where * is modular. I use it for Save, Back, Cancel, Expand, Yes, No, etc buttons with simple text. Here's an example:
And I press the "Create a Note" FAB button
And I am on the Create a Note Screen
Then I tap Back
>> And I press the "Yes" button
Now currently with my app on android there are multiple versions of the "Back" button and they're not all formatted the same. Some have texts that reads "BACK", some are "Back", and some are "back". I designed a series of if statements to handle this discrepancy until I can get the developers to standardize the text they use for these buttons:
Then(/^I press the "([^"]*)" button$/) do |button_text|
sleep 1
#button_text = button_text
binding.pry
if find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").displayed? == true
find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").click()
else
#button_text.capitalize()
if find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").displayed? == true
find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").click()
else
#button_text.upcase()
if find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").displayed? == true
find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").click()
else
#button_text.downcase()
if find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").displayed? == true
find_element(xpath: "//android.widget.Button[#text='#{#button_text}']").click()
else
fail("Could not find a permutation of that button")
end
end
end
end
sleep 2
end
My thinking is that I'll save the button_text argument to a variable, #button_text, and then use the .displayed? method to check if that version of the button is available. If it is I pass the .click() method, and if it isn't I alter the text of the variable via the .capitalize, .upcase, and .downcase methods. I'm sure that using nested if statements isn't the most ideal way to do this so I would love some assistance on a better way to write that statement.
The issues I receive is I get "An element could not be located using the given search parameters" error whenever I get to this line of code. It seems like the .displayed? method doesn't return a value and triggers appium to stop the test.
I want appium to check if that version of the button is present, then adjust the variable and check the new version for upcase, downcase, and capitalize. Any and all assistance would be greatly appreciated.
When you're finding the elements, try setting their text to all uppercase, and then checking for one version of the word that you're searching for.
I.e. BacK or back or BACK would all become "BACK"

Pythonic way of applying changes on closing a dialog window

I couldn't find any useful resources for this subject. I hope I can find some guidance here.
I made a dialog window class using Glade, Gtk (3.10) and Python 3. It has about 30 options that can be changed. In the init function I set up the whole dialog window and set the options to the current value. I also define a bool-variable that stores if any of the widgets was changed:
self.settings_changed = False
So for each widget I set up a function that catches the "change-signal" and does the following:
def on_checkbutton_line_width_changed(self, widget):
#Set setting_changed to True so that the dialog knows something changed
self.settings_changed = True
#Store the changed value in a temporary variable
self.temp_checkbutton_value = widget.get_active()
Now when I click "Cancel" on the dialog I just don't apply any of the temporary values. But when I click "Apply" I want all changed variables to be applied. But here is my problem: Of those 30 changed variables only a few exist and all the others would lead to a lot of AttributeErrors, because the temporary variable doesn't exist.
I tried avoiding the errors by using a lot of try-except functions:
try:
self.dataclass.set_checkbutton(self.temp_checkbutton_value)
except:
pass
Is there a easier (and shorter) way to solve this? I imagine that there should be a way to build a queue of changes that are executed after each other after clicking on "Apply", but my potato-like python skills have so far not helped me in solving this.
Here's an example that might help:
class MyWidget:
def __init__(self):
self.changes = []
def cancel_changes(self):
self.changes.clear()
def change_name(self, new_name):
self.changes.append(('change_name', new_name))
def change_color(self, new_color):
self.changes.append(('change_color', new_color))
def apply_changes(self):
for change in self.changes:
print("{} - {}".format(change[0], change[1])
alternatively you could do something like:
self.changes.append(lambda: self.dataclass.set_checkoutbutton(value))
and then apply changes would be:
for change in self.changes:
change()

handling event in qtruby

I trying Qt with Ruby and QtDesigner but I don't understand how to handle events. I read and tried signals and slots but I don't see how I customize behavior for example if I want to trigger an action when I click on a button.
From the home page:
button = Qt::PushButton.new('Quit') do
connect(SIGNAL :clicked) { Qt::Application.instance.quit }
end

FireFox4 doesn't recognize event object, anybody else having this issue?

I wonder if anybody else is having this issue. I'm using Firefox 4 and I'm debugging a function from an onclick event using Firebug. Now, to be sure, I checked the stack and it clearly shows that an onclick event was fired. However, when I type "event" (without quotse) in the watch pane, it says it's undefined. Why? Now it recognizes "Event", but not "event". Is anybody else having this issue?
Thank you.
When debugging inside of your event function, add a watch for arguments[0]; this is the event object you are looking for.
Modern, standards-compliant browsers don't use a window.event object in the manner that some versions of Internet Explorer do.
In these browsers, the event is passed to the event handler as an argument. So if you do something like the following...
function foo(bar) {
// do stuff
}
document.getElementById("myElement").onclick = foo;
...then when #myElement is clicked, the browser will execute foo(bar), where bar is the event object. If you need to see the event object's details, you would have to set a breakpoint inside of foo and add a watch for bar or for arguments[0].

Resources