Unable to interact with Windows file upload box with watir - watir

I am writing a watir-webdriver test script to upload a file to app. My application uses kendo widgets, e.g. below
http://demos.telerik.com/kendo-ui/upload/index
I am able to interact with the windows dialog box when I debug the code, but when I execute it together, it times out as the windows dialog modal never seems to get the focus. Code below:
require 'win32ole'
sleep 1
wsh = WIN32OLE.new('Wscript.Shell')
## open the windows dialog modal.
#browser.div(:class => "k-button k-upload-button").click
### Code times out after the above click, it never executes the below steps as app looses focus, don't know how I can switch the focus to windows modal and execute below code.
#browser.windows.last.use do
sleep 2
wsh.AppActivate("File Upload")
sleep 2
wsh.SendKeys "{TAB}"
sleep 1
wsh.SendKeys("file path")
sleep 1
wsh.SendKeys "~"
end
Error :
Net::ReadTimeout (Net::ReadTimeout)

I was able to figure the solution for my problem by multi-threading .
def threaded
#filepath= upload_filepath ## reading from YAML
t1=Thread.new { select_files }
t2=Thread.new { file_upload(#filepath) }
t1.join
t2.join
end
def select_files_click_button
#browser.div(:class => "k-button k-upload-button").click
sleep 2
end
def file_upload(filepath)
#def file_upload
require 'win32ole'
sleep 3
wsh = WIN32OLE.new('Wscript.Shell')
sleep 2
wsh.AppActivate("File Upload")
sleep 4
wsh.SendKeys "{TAB}"
sleep 3
wsh.SendKeys("#{filepath}")
sleep 2
wsh.SendKeys "~"
sleep 2
#browser.windows.first.use
end

Related

Detect when no buttons are being pushed PyQt

I have a GUI that is controlling a device over USB.
The way I have it set up is with basically two buttons, forward and back, and while the button is pressed that function is transmitted to the motor, when the button is released, the off signal is triggered once.
def on_release():
print('Off')
self.off()
def on_click():
print('forward')
self.forward()
button = QPushButton('Cut', self)
button.move(100,70)
button.pressed.connect(on_click)
button.released.connect(on_release)
def on_click():
print('back')
self.back()
button = QPushButton('back', self)
button.move(200,70)
button.pressed.connect(on_click)
button.released.connect(on_release)
I've recently encountered an interesting failure mode where if the USB connection is paused (in my case I was using GDB and hit a breakpoint, released the button, then released the breakpoint) at the moment the button is released, the kill signal is never sent and the motor will continue going back or forward forever. (It can be killed by either clicking one of back or forward and releasing, or by killing USB entirely")
I already have protections in place (a threaded heartbeat signal) for turning off the motor in the condition that a USB connection is severed but I'd like to make this fail a little more safely in case that one particular USB off transmission were to fail.
Is there a way for me to check if no buttons are pressed so I can use this to trigger the off signal?
Learning material from tjmarkham stepper.py script at [https://github.com/tjmarkham/python-stepper] for a raspberry Pi which can be put behind your buttons:
#CURRENT APPLICATION INFO
#200 steps/rev
#12V, 350mA
#Big Easy driver = 1/16 microstep mode
#Turn a 200 step motor left one full revolution: 3200
from time import sleep
import RPi.GPIO as gpio #https://pypi.python.org/pypi/RPi.GPIO
#import exitHandler #uncomment this and line 58 if using exitHandler
class stepper:
#instantiate stepper
#pins = [stepPin, directionPin, enablePin]
def __init__(self, pins):
#setup pins
self.pins = pins
self.stepPin = self.pins[0]
self.directionPin = self.pins[1]
self.enablePin = self.pins[2]
#use the broadcom layout for the gpio
gpio.setmode(gpio.BCM)
#set gpio pins
gpio.setup(self.stepPin, gpio.OUT)
gpio.setup(self.directionPin, gpio.OUT)
gpio.setup(self.enablePin, gpio.OUT)
#set enable to high (i.e. power is NOT going to the motor)
gpio.output(self.enablePin, True)
print("Stepper initialized (step=" + self.stepPin + ", direction=" + self.directionPin + ", enable=" + self.enablePin + ")")
#clears GPIO settings
def cleanGPIO(self):
gpio.cleanup()
#step the motor
# steps = number of steps to take
# dir = direction stepper will move
# speed = defines the denominator in the waitTime equation: waitTime = 0.000001/speed. As "speed" is increased, the waitTime between steps is lowered
# stayOn = defines whether or not stepper should stay "on" or not. If stepper will need to receive a new step command immediately, this should be set to "True." Otherwise, it should remain at "False."
def step(self, steps, dir, speed=1, stayOn=False):
#set enable to low (i.e. power IS going to the motor)
gpio.output(self.enablePin, False)
#set the output to true for left and false for right
turnLeft = True
if (dir == 'right'):
turnLeft = False;
elif (dir != 'left'):
print("STEPPER ERROR: no direction supplied")
return False
gpio.output(self.directionPin, turnLeft)
stepCounter = 0
waitTime = 0.000001/speed #waitTime controls speed
while stepCounter < steps:
#gracefully exit if ctr-c is pressed
#exitHandler.exitPoint(True) #exitHandler.exitPoint(True, cleanGPIO)
#turning the gpio on and off tells the easy driver to take one step
gpio.output(self.stepPin, True)
gpio.output(self.stepPin, False)
stepCounter += 1
#wait before taking the next step thus controlling rotation speed
sleep(waitTime)
if (stayOn == False):
#set enable to high (i.e. power is NOT going to the motor)
gpio.output(self.enablePin, True)
print("stepperDriver complete (turned " + dir + " " + str(steps) + " steps)")
teststepper.py:
from Stepper import Stepper
#stepper variables
#[stepPin, directionPin, enablePin]
testStepper = Stepper([22, 17, 23])
#test stepper
testStepper.step(3200, "right"); #steps, dir, speed, stayOn

Raspberry PI with GPIO Input buttons

I have a PI running with 4 GPIO input ports.
The target is, if one the 4 buttons will be pressed, a mp3 file should be played, i.e. button1 = file1.mp3, button2 = file2.mp3 and so on.
It seems to be no so complicate, but 'the devil is in the detail' :-)
This is my code for 2 buttons at moment :
#!/usr/bin/env python
#coding: utf8
import time
from time import sleep
import os
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
def my_callback_1(channel):
print("Button 23 Pressed")
os.system('omxplayer -o both /root/1.mp3')
sleep(10)
def my_callback_2(channel):
print("Button 24 Pressed")
os.system('omxplayer -o both /root/2.mp3')
sleep(10)
GPIO.add_event_detect(23, GPIO.RISING, callback=my_callback_1, bouncetime=200)
GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback_2, bouncetime=200)
try:
while 1:
time.sleep(0.5)
except KeyboardInterrupt:
# exits when you press CTRL+C
print(" Bye Bye")
except:
print("Other error or exception occurred!")
finally:
GPIO.cleanup() # this ensures a clean exit
The sleep time is set for the longer of the mp3 file.
Its working, but not like I expected.
The problem is, when a buttons will be pushed while a file is already playing, the PI keeps the button push in a buffer and play the file after the current file in a loop.
Imagine, somebody will push 5 times the same button, 5 times the same mp3 file will be played in a loop.
So I searching for a solution like this:
While a file is playing, all Input buttons should be "disabled" for this time. When the mp3 file paying is finished, the buttons should be "re-enabled" and another button can be pushed.
How can I this ? Thanks for your help.
I don't see a simple way to do this without adding threads. Note that you are implicitly already using threads behind the scenes with add_event_detect(), which runs the callbacks in separate threads. If add_event_detect doesn't support suppressing the button presses (which I don't think it does), then you can thread it in one of two ways - using python threads or processes, or a simpler way by using bash.
To use background processes in bash, remove your add_event_detect calls, and then in your while loop, you'd do something like (untested):
started_23 = 0
while True:
if GPIO.input(23) and time.time() - started_23 > 10:
started_23 = time.time()
print("Button 23 Pressed")
os.system('omxplayer -o both /root/1.mp3 &')
time.sleep(0.200)
Note the ampersand added to the system() call - that will run the omxplayer in the background. And the started_23 variable keeps track of when the sound was started in order to prevent replaying it for another 10 seconds. You may way to increase that to include the length of the file time. You can similarly add in code for GPIO 24 in the same loop.
Thanks for help, Brian. You brought me in the right direction !
I got it. Its working now as I described above.
Here my code :
try:
vtc1 = 8 # Time Audiofile 1
vtc2 = 11 # Time Audiofile 2
vtc3 = 0 # Time Audiofile 3
vtc4 = 0 # Time Audiofile 4
vtc = 0 # Current AudioFileTime
started_t = 0 # Started Time
while True:
if GPIO.input(23) and time.time() - started_t > vtc:
vtc = vtc1
started_t = time.time()
print("Button 23 Pressed")
os.system('omxplayer -o both /root/1.mp3 &')
time.sleep(0.200)
if GPIO.input(24) and time.time() - started_t > vtc:
vtc = vtc2
started_t = time.time()
print("Button 24 Pressed")
os.system('omxplayer -o both /root/2.mp3 &')
time.sleep(0.200)
The problem was, that the seconded file was started before the first was finished. Because the code did not know the longer of currently played file. So I put the time of the audiofile in the "vtc" value when this file were executed.
If you push another button, it calculate the time playing with the current file time "vtc". That's it.
Thanks again.

How to multithread in PowerBuidler

how can I open a window on a separate thread?
w_main
open process window btn code:
//instance variable
stopper = false
if SharedObjectRegister("w_sep_thread", "SendThread") = success! then
messagebox('', 'Success')
else
messagebox('', 'Unsuccessful')
end if
open(w_sep_thread)
stop process btn code:
stopper = true
w_sep_thread
start process btn code:
int i
do while w_main.stopper = false
sleep(1)
st_1.text = string(i + 1)
loop
messagebox('', 'Stopped')
If I click the start process btn both the UIs still freeze, but the SharedObjectRegister function returns success
As Chris Pollach says "Mutli-threading in PB would only be done using NVUO's not Window classes". I hope it helps this thread: click here

Watir-webdriver hangs fro 1-2 minutes for "repeat" scenario

I have the next method in my page object:
def open_random_report(count)
opened_reports = 0
rows = self.how_many_reports_present
cells = self.browser.divs(:class=>/x-grid-cell-inner./)
type_position = self.calculate_report_type_position
row_length = 0
self.browser.divs(:class=>"x-column-header-inner").each do |d|
if d.visible?
row_length += 1
end
end
while opened_reports < count.to_i do
$start=Time.now
r = Random.new
row = r.rand(rows - 2)
cell_position = type_position + (row * row_length) - 1
cells[cell_position].a.click
opened_reports += 1
sleep 1
self.close_report
$finish=Time.now
p "#{$finish} Report# #{opened_reports} - #{$finish - $start}"
f = File.new('log.txt', 'a')
f.puts "#{$finish} Report# #{opened_reports} - #{$finish - $start}"
f.close
end
end
This code clicks on random cell in the table(table is represented by the extjs-grid) and it works ok except for one thing: from time to time driver hangs for 1-2 minutes. There is no pattern for hanging, it can happens one time during a run or may happen 10 times during the run.
One more detail: When driver click on cell the app generates pdf report that will be shown to the user in preview window. I don't care about the report my goal is just to open reports so I'm closing preview window despite that fact that pdf has already completely loaded or not.
Any ideas why such hanging may happen? Maybe there is some problem with code?

Watir implicit_wait doesn't seem to work

We are currently using watir-webdriver (0.6.2) with firefox to run acceptance tests.
Our tests take a long time to run, and often fail with timeout errors.
We wanted to decrease the timeout time, for them to fail faster.
We tried:
browser = Watir::Browser.new("firefox")
browser.driver.manage.timeouts.implicit_wait=3
However, we are still experiencing 30s timeouts.
We couldn't find any documentation or question regarding this issue. Does anyone know how to configure Watir waiting timeouts properly?
It depends exactly what you mean by 'timeout'. AFAIK there are three different definitions of timeout commonly discussed when talking about Watir-Webdriver:
How long does the browser wait for a page to load?
How long does Watir-Webdriver explicitly wait before considering an element 'not present' or 'not visible' when told to wait via the '.when_present' function
How long does Watir-Webdriver implicitly wait for an object to appear before considering an element 'not present' or 'not visible' (when not waiting via explicitly call see #2)
#1: Page load
Justin Ko is right that you can set page load timeout as described if your goal is to modify that, though it looks like the canonical way to do that is to set the client timeout before creating the browser and passing it to the browser on creation:
client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 180 # seconds – default is 60
b = Watir::Browser.new :firefox, :http_client => client
- Alistair Scott, 'How do I change the page load Timeouts in Watir-Webdriver'
#2: Explicit timeout
But I think #p0deje is right in saying you are experiencing explicit timeouts, though it's not possible to say for sure without seeing your code. In the below I experienced the explicit declaration overriding the implicit (I am unsure if that's intentional):
b = Watir::Browser.new :firefox
b.driver.manage.timeouts.implicit_wait = 3
puts Time.now #=> 2013-11-14 16:24:12 +0000
begin
browser.link(:id => 'someIdThatIsNotThere').when_present.click
rescue => e
puts e #=> timed out after 30 seconds, waiting for {:id=>"someIdThatIsNotThere", :tag_name=>"a"} to become present
end
puts Time.now #=> 2013-11-14 16:24:43 +0000
Watir-Webdriver will wait 30 seconds before failure by default thanks to 'when_present'. Alternatively you can say 'when_present(10)' to alter the default and wait 10 seconds. (Watir-Webdriver > Watir::Wait#when_present.) I can not divine any way to do this globally. Unless you find such a thing - and please tell me if you do - it must be done on each call. :( Edit: Fellow answerer Justin Ko gave me the answer as to how to do what I described above. Edit 2: #jarib added this to Watir, per #justinko in the linked answer: "Update: This monkey patch has been merged into watir-webdriver and so will no longer be needed in watir-webdriver v0.6.5. You will be able to set the timeout using: Watir.default_timeout = 90"
#3 Implicit timeout
The code you provided sets the time Watir-Webdriver will wait for any element to be come present without you explicitly saying so:
b = Watir::Browser.new :firefox
b.driver.manage.timeouts.implicit_wait = 3
puts Time.now #=> 2013-11-14 16:28:33 +0000
begin
browser.link(:id => 'someIdThatIsNotThere').when_present.click
rescue => e
puts e #=> unable to locate element, using {:id=>"someIdThatIsNotThere", :tag_name=>"a"}
end
puts Time.now #=> 2013-11-14 16:28:39 +0000
The implicit_wait is the amount of time selenium-webdriver tries to find an element before timing out. The default is 0 seconds. By changing it to "3", you are actually increasing the amount of time that it will wait.
I am guessing that you actually want to change the timeout for waiting for the page to load (rather than for finding an element). This can be done with:
browser.driver.manage.timeouts.page_load = 3
For example, we can say to only wait 0 seconds when loading Google:
require 'watir-webdriver'
browser = Watir::Browser.new :firefox
browser.driver.manage.timeouts.page_load = 0
browser.goto 'www.google.ca'
#=> Timed out waiting for page load. (Selenium::WebDriver::Error::TimeOutError)
Update: Since Watir 6.5, the default timeout is configurable using
Watir.default_timeout = 3
We experienced the same issue and chose to override Watir methods involving timeouts, namely
Watir::Wait.until { ... }
Watir::Wait.while { ... }
object.when_present.set
object.wait_until_present
object.wait_while_present
Here is the code, you can put it in your spec_helper.rb if using rspec
# method wrapping technique adapted from https://stackoverflow.com/a/4471202/177665
def override_timeout(method_name, new_timeout = 3)
if singleton_methods.include?(method_name)
old_method = singleton_class.instance_method(method_name)
define_singleton_method(method_name) do |timeout = new_timeout, *args, &block|
old_method.bind(self).(timeout, *args, &block)
end
else
old_method = instance_method(method_name)
define_method(method_name) do |timeout = new_timeout, *args, &block|
old_method.bind(self).(timeout, *args, &block)
end
end
end
# override default Watir timeout from 30 seconds to 3 seconds
module Watir
module Wait
override_timeout(:until)
override_timeout(:while)
end
module EventuallyPresent
override_timeout(:when_present, 5) # 5 secs here
override_timeout(:wait_until_present)
override_timeout(:wait_while_present)
end
end
We used answer from https://stackoverflow.com/a/4471202/177665 to get it working.

Resources