sahi 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.txt +7 -0
- data/lib/sahi.rb +421 -0
- data/test/elementstub_test.rb +38 -0
- data/test/sahi_test.rb +391 -0
- metadata +91 -0
data/README.txt
ADDED
data/lib/sahi.rb
ADDED
@@ -0,0 +1,421 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'cgi'
|
3
|
+
require 'guid'
|
4
|
+
require 'Platform'
|
5
|
+
|
6
|
+
module Sahi
|
7
|
+
# The Browser class controls different browser via Sahi's proxy.
|
8
|
+
# Thank you Sai Venkat for helping kickstart the ruby driver.
|
9
|
+
#
|
10
|
+
# Author:: Narayan Raman (mailto:narayan@sahi.co.in)
|
11
|
+
# Copyright:: Copyright (c) 2006 V Narayan Raman
|
12
|
+
# License:: Apache License, Version 2.0
|
13
|
+
#
|
14
|
+
# Download Sahi from http://sahi.co.in/w/
|
15
|
+
# Java 1.5 or greater is needed to run Sahi.
|
16
|
+
#
|
17
|
+
# Start Sahi:
|
18
|
+
# cd sahi\userdata\bin
|
19
|
+
# start_sahi.bat
|
20
|
+
#
|
21
|
+
# or
|
22
|
+
#
|
23
|
+
# cd sahi/userdata/bin
|
24
|
+
# start_sahi.sh
|
25
|
+
#
|
26
|
+
# Point the browser proxy settings to localhost 9999.
|
27
|
+
#
|
28
|
+
|
29
|
+
class Browser
|
30
|
+
attr_accessor :proxy_host, :proxy_port, :print_steps, :sahisid, :popup_name
|
31
|
+
|
32
|
+
# Takes browser_path and browser_options
|
33
|
+
# Various browser options needed to initialize the Browser object are:
|
34
|
+
#
|
35
|
+
# Internet Explorer 6&7:
|
36
|
+
# browser_path = "C:\\Program Files\\Internet Explorer\\iexplore.exe"
|
37
|
+
# browser_options = ""
|
38
|
+
#
|
39
|
+
# Internet Explorer 8:
|
40
|
+
# browser_path = "C:\\Program Files\\Internet Explorer\\iexplore.exe"
|
41
|
+
# browser_options = "-nomerge"
|
42
|
+
#
|
43
|
+
# Firefox:
|
44
|
+
# userdata_dir = "D:/sahi/sf/sahi_993/userdata" # path to Sahi's userdata directory.
|
45
|
+
# browser_path = "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
|
46
|
+
# browser_options = "-profile # {userdata_dir}/browser/ff/profiles/sahi0 -no-remote"
|
47
|
+
#
|
48
|
+
# Chrome:
|
49
|
+
# userdata_dir = "D:/sahi/sf/sahi_993/userdata" # path to Sahi's userdata directory.
|
50
|
+
# browser_path = "C:\\Documents and Settings\\YOU_THE_USER\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe"
|
51
|
+
# browser_options = "--user-data-dir=# {userdata_dir}\browser\chrome\profiles\sahi$threadNo"
|
52
|
+
#
|
53
|
+
# Safari:
|
54
|
+
# browser_path = "C:\\Program Files\\Safari\Safari.exe"
|
55
|
+
# browser_options = ""
|
56
|
+
#
|
57
|
+
# Opera:
|
58
|
+
# browser_path = "C:\\Program Files\\Opera\\opera.exe"
|
59
|
+
# browser_options = ""
|
60
|
+
|
61
|
+
def initialize(browser_path, browser_options)
|
62
|
+
@proxy_host = "localhost"
|
63
|
+
@proxy_port = 9999
|
64
|
+
@browser_path = browser_path
|
65
|
+
@browser_options = browser_options
|
66
|
+
@popup_name = nil
|
67
|
+
@sahisid = nil
|
68
|
+
@print_steps = false
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_proxy()
|
72
|
+
begin
|
73
|
+
response("http://#{@proxy_host}:#{@proxy_port}/_s_/spr/blank.htm")
|
74
|
+
rescue
|
75
|
+
raise "Sahi proxy is not available. Please start the Sahi proxy."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
#opens the browser
|
80
|
+
def open()
|
81
|
+
check_proxy()
|
82
|
+
|
83
|
+
@sahisid = Guid.new.to_s
|
84
|
+
cmd = "#{@browser_path} #{@browser_options} http://sahi.example.com/_s_/dyn/Driver_start?sahisid=#{@sahisid}&startUrl=#{CGI.escape("http://sahi.example.com/_s_/dyn/Driver_initialized")}"
|
85
|
+
|
86
|
+
if Platform::OS == :win32
|
87
|
+
require "win32/process"
|
88
|
+
@pid = Process.create(:app_name => cmd,
|
89
|
+
:process_inherit => true,
|
90
|
+
:thread_inherit => true,
|
91
|
+
:inherit => true).process_id
|
92
|
+
else
|
93
|
+
@pid = fork { exec(cmd) }
|
94
|
+
end
|
95
|
+
|
96
|
+
i = 0
|
97
|
+
while (i < 500)
|
98
|
+
i+=1
|
99
|
+
break if is_ready?
|
100
|
+
sleep(0.1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def is_ready?
|
105
|
+
return "true".eql?(exec_command("isReady"))
|
106
|
+
end
|
107
|
+
|
108
|
+
def exec_command(cmd, qs={})
|
109
|
+
res = response("http://#{@proxy_host}:#{@proxy_port}/_s_/dyn/Driver_" + cmd, {"sahisid"=>@sahisid}.update(qs))
|
110
|
+
return res
|
111
|
+
end
|
112
|
+
|
113
|
+
def response(url, qs={})
|
114
|
+
return Net::HTTP.post_form(URI.parse(url), qs).body
|
115
|
+
end
|
116
|
+
|
117
|
+
def execute()
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def navigate_to(url, forceReload=false)
|
122
|
+
execute_step("_sahi._navigateTo(\"" + url + "\", "+ (forceReload.to_s()) +")");
|
123
|
+
end
|
124
|
+
|
125
|
+
def execute_step(step)
|
126
|
+
if popup?()
|
127
|
+
step = "_sahi._popup(#{Utils.quoted(@popup_name)})." + step
|
128
|
+
end
|
129
|
+
puts step if @print_steps
|
130
|
+
exec_command("setStep", {"step" => step})
|
131
|
+
i = 0
|
132
|
+
while (i < 500)
|
133
|
+
sleep(0.1)
|
134
|
+
i+=1
|
135
|
+
check_done = exec_command("doneStep")
|
136
|
+
done = "true".eql?(check_done)
|
137
|
+
|
138
|
+
error = check_done.index("error:") == 0
|
139
|
+
return if done
|
140
|
+
if (error)
|
141
|
+
raise check_done
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def method_missing(m, *args, &block)
|
147
|
+
return ElementStub.new(self, m.to_s, args)
|
148
|
+
end
|
149
|
+
|
150
|
+
# evaluates a javascript expression on the browser and fetches its value
|
151
|
+
def fetch(expression)
|
152
|
+
key = "___lastValue___" +Guid.new.to_s()
|
153
|
+
execute_step("_sahi.setServerVarPlain('"+key+"', " + expression + ")")
|
154
|
+
return check_nil(exec_command("getVariable", {"key" => key}))
|
155
|
+
end
|
156
|
+
|
157
|
+
def check_nil(s)
|
158
|
+
return (s == "null") ? nil : s
|
159
|
+
end
|
160
|
+
|
161
|
+
# closes the browser
|
162
|
+
def close()
|
163
|
+
if popup?()
|
164
|
+
execute_step("_sahi._closeWindow()");
|
165
|
+
else
|
166
|
+
Process.kill(9, @pid) if @pid
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# sets the speed of execution. The speed is specified in milli seconds
|
171
|
+
def set_speed(ms)
|
172
|
+
exec_command("setSpeed", {"speed"=>ms})
|
173
|
+
end
|
174
|
+
|
175
|
+
# represents a popup window. The name is either the window name or its title.
|
176
|
+
def popup(name)
|
177
|
+
win = Browser.new(@browser_path, @browser_options)
|
178
|
+
win.proxy_host = @proxy_host
|
179
|
+
win.proxy_port = @proxy_port
|
180
|
+
win.sahisid = @sahisid
|
181
|
+
win.print_steps = @print_steps
|
182
|
+
win.popup_name = name
|
183
|
+
return win
|
184
|
+
end
|
185
|
+
|
186
|
+
def popup?()
|
187
|
+
return @popup_name != nil
|
188
|
+
end
|
189
|
+
|
190
|
+
# returns the message last alerted on the browser
|
191
|
+
def last_alert()
|
192
|
+
return fetch("_sahi._lastAlert()")
|
193
|
+
end
|
194
|
+
|
195
|
+
# resets the last alerted message
|
196
|
+
def clear_last_alert()
|
197
|
+
execute_step("_sahi._clearLastAlert()")
|
198
|
+
end
|
199
|
+
|
200
|
+
# returns the last confirm message
|
201
|
+
def last_confirm()
|
202
|
+
return fetch("_sahi._lastConfirm()")
|
203
|
+
end
|
204
|
+
|
205
|
+
# resets the last confirm message
|
206
|
+
def clear_last_confirm()
|
207
|
+
execute_step("_sahi._clearLastConfirm()")
|
208
|
+
end
|
209
|
+
|
210
|
+
# set an expectation to press OK (true) or Cancel (false) for specific confirm message
|
211
|
+
def expect_confirm(message, input)
|
212
|
+
execute_step("_sahi._expectConfirm(#{Utils.quoted(message) }, #{input})")
|
213
|
+
end
|
214
|
+
|
215
|
+
# returns the last prompted message
|
216
|
+
def last_prompt()
|
217
|
+
return fetch("_sahi._lastPrompt()")
|
218
|
+
end
|
219
|
+
|
220
|
+
# clears the last prompted message
|
221
|
+
def clear_last_prompt()
|
222
|
+
execute_step("_sahi._clearLastPrompt()")
|
223
|
+
end
|
224
|
+
|
225
|
+
# set an expectation to set given value for specific prompt message
|
226
|
+
def expect_prompt(message, input)
|
227
|
+
execute_step("_sahi._expectPrompt(#{Utils.quoted(message)}, #{Utils.quoted(input) })")
|
228
|
+
end
|
229
|
+
|
230
|
+
# get last downloaded file's name
|
231
|
+
def last_downloaded_filename()
|
232
|
+
return fetch("_sahi._lastDownloadedFileName()")
|
233
|
+
end
|
234
|
+
|
235
|
+
# clear last downloaded file's name
|
236
|
+
def clear_last_downloaded_filename()
|
237
|
+
execute_step("_sahi._clearLastDownloadedFileName()")
|
238
|
+
end
|
239
|
+
|
240
|
+
# Save the last downloaded file to specified path
|
241
|
+
def save_downloaded(file_path)
|
242
|
+
execute_step("_sahi._saveDownloadedAs(#{Utils.quoted(file_path)})")
|
243
|
+
end
|
244
|
+
|
245
|
+
# make specific url patterns return dummy responses. Look at _addMock documentation.
|
246
|
+
def add_url_mock(url_pattern, clazz=nil)
|
247
|
+
clazz = "MockResponder_simple" if !clazz
|
248
|
+
execute_step("_sahi._addMock(#{Utils.quoted(url_pattern)}, #{Utils.quoted(clazz)})")
|
249
|
+
end
|
250
|
+
|
251
|
+
# reverse effect of add_url_mock
|
252
|
+
def remove_url_mock(url_pattern)
|
253
|
+
execute_step("_sahi._removeMock(#{Utils.quoted(url_pattern)})")
|
254
|
+
end
|
255
|
+
|
256
|
+
# return window title
|
257
|
+
def title()
|
258
|
+
return fetch("_sahi._title()")
|
259
|
+
end
|
260
|
+
|
261
|
+
# waits for specified time (in seconds)
|
262
|
+
# if a block is passed, it will wait till the block evaluates to true or till the specified timeout, which ever is earlier.
|
263
|
+
def wait(timeout)
|
264
|
+
total = 0;
|
265
|
+
interval = 0.2;
|
266
|
+
|
267
|
+
if !block_given?
|
268
|
+
sleep(timeout)
|
269
|
+
return
|
270
|
+
end
|
271
|
+
|
272
|
+
while (total < timeout)
|
273
|
+
sleep(interval);
|
274
|
+
total += interval;
|
275
|
+
begin
|
276
|
+
return if yield
|
277
|
+
rescue Exception=>e
|
278
|
+
puts e
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
# This class is a stub representation of various elements on the browser
|
287
|
+
# Most of the methods are implemented via method missing.
|
288
|
+
#
|
289
|
+
# All APIs available in Sahi are available in ruby. The full list is available here: http://sahi.co.in/w/browser-accessor-apis
|
290
|
+
#
|
291
|
+
# Most commonly used action methods are:
|
292
|
+
# click - for all elements
|
293
|
+
# mouse_over - for all elements
|
294
|
+
# focus - for all elements
|
295
|
+
# remove_focus - for all elements
|
296
|
+
# check - for checkboxes or radio buttons
|
297
|
+
# uncheck - for checkboxes
|
298
|
+
|
299
|
+
class ElementStub
|
300
|
+
@@actions = {"click"=>"click", "mouse_over"=>"mouseOver",
|
301
|
+
"focus"=>"focus", "remove_focus"=>"removeFocus",
|
302
|
+
"check"=>"check", "uncheck"=>"uncheck"}
|
303
|
+
def initialize (browser, type, identifiers)
|
304
|
+
@type = type
|
305
|
+
@browser = browser
|
306
|
+
@identifiers = identifiers
|
307
|
+
end
|
308
|
+
|
309
|
+
def method_missing(m, *args, &block)
|
310
|
+
key = m.to_s
|
311
|
+
if @@actions.key?(key)
|
312
|
+
_perform(@@actions[key])
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def _perform(type)
|
317
|
+
step = "_sahi._#{type}(#{self.to_s()})"
|
318
|
+
@browser.execute_step(step)
|
319
|
+
end
|
320
|
+
|
321
|
+
# drag element and drop on another element
|
322
|
+
def dragAndDropOn(el2)
|
323
|
+
@browser.execute_step("_sahi._dragDrop(#{self.to_s()}, #{el2.to_s()})")
|
324
|
+
end
|
325
|
+
|
326
|
+
# choose option in a select box
|
327
|
+
def choose(val)
|
328
|
+
@browser.execute_step("_sahi._setSelected(#{self.to_s()}, #{Utils.quoted(val)})")
|
329
|
+
end
|
330
|
+
|
331
|
+
# sets the value for textboxes or textareas. Also triggers necessary events.
|
332
|
+
def value=(val)
|
333
|
+
@browser.execute_step("_sahi._setValue(#{self.to_s()}, #{Utils.quoted(val)})")
|
334
|
+
end
|
335
|
+
|
336
|
+
# returns value of textbox or textareas and other relevant input elements
|
337
|
+
def value()
|
338
|
+
return @browser.fetch("#{self.to_s()}.value")
|
339
|
+
end
|
340
|
+
|
341
|
+
# fetches value of specified attribute
|
342
|
+
def fetch(attr=nil)
|
343
|
+
return attr ? @browser.fetch("#{self.to_s()}.#{attr}") : @browser.fetch("#{self.to_s()}")
|
344
|
+
end
|
345
|
+
|
346
|
+
# Emulates setting filepath in a file input box.
|
347
|
+
def file=(val)
|
348
|
+
@browser.execute_step("_sahi._setFile(#{self.to_s()}, #{Utils.quoted(val)})")
|
349
|
+
end
|
350
|
+
|
351
|
+
# returns inner text of any element
|
352
|
+
def text()
|
353
|
+
return @browser.fetch("_sahi._getText(#{self.to_s()})")
|
354
|
+
end
|
355
|
+
|
356
|
+
# returns checked state of checkbox or radio button
|
357
|
+
def checked()
|
358
|
+
return fetch("checked") == "true";
|
359
|
+
end
|
360
|
+
|
361
|
+
# returns selected text from select box
|
362
|
+
def selected_text()
|
363
|
+
return @browser.fetch("_sahi._getSelectedText(#{self.to_s()})")
|
364
|
+
end
|
365
|
+
|
366
|
+
# returns a stub with a DOM "near" relation to another element
|
367
|
+
# Eg.
|
368
|
+
# browser.button("delete").near(browser.cell("User One")) will denote the delete button near the table cell with text "User One"
|
369
|
+
def near(el2)
|
370
|
+
@identifiers << ElementStub.new(@browser, "near", [el2])
|
371
|
+
return self
|
372
|
+
end
|
373
|
+
|
374
|
+
# returns a stub with a DOM "in" relation to another element
|
375
|
+
# Eg.
|
376
|
+
# browser.image("plus.gif").in(browser.div("Tree Node 2")) will denote the plus icon inside a tree node with text "Tree Node 2"
|
377
|
+
def in(el2)
|
378
|
+
@identifiers << ElementStub.new(@browser, "in", [el2])
|
379
|
+
return self
|
380
|
+
end
|
381
|
+
|
382
|
+
|
383
|
+
# specifies exacts coordinates to click inside an element. The coordinates are relative to the element. x is from left and y is from top. Can be negative to specify other direction
|
384
|
+
# browser.button("Menu Button with Arrow on side").xy(-5, 10).click will click on the button, 5 pixels from right and 10 pixels from top.
|
385
|
+
def xy(x, y)
|
386
|
+
return ElementStub.new(@browser, "xy", [self, x, y])
|
387
|
+
end
|
388
|
+
|
389
|
+
# denotes the DOM parentNode of element.
|
390
|
+
# If tag_name is specified, returns the parent element which matches the tag_name
|
391
|
+
# occurrence finds the nth parent of a particular tag_name
|
392
|
+
# eg. browser.cell("inner nested cell").parent_node("TABLE", 3) will return the 3rd encapsulating table of the given cell.
|
393
|
+
def parent_node(tag_name="ANY", occurrence=1)
|
394
|
+
return ElementStub.new(@browser, "parentNode", [self]);
|
395
|
+
end
|
396
|
+
|
397
|
+
# returns true if the element exists on the browser
|
398
|
+
def exists?
|
399
|
+
return "true".eql?(@browser.fetch("_sahi._exists(#{self.to_s()})"))
|
400
|
+
end
|
401
|
+
|
402
|
+
# returns true if the element exists and is visible on the browser
|
403
|
+
def visible?
|
404
|
+
return "true".eql?(@browser.fetch("_sahi._isVisible(#{self.to_s()})"))
|
405
|
+
end
|
406
|
+
|
407
|
+
def to_s
|
408
|
+
return "_sahi._#{@type }(#{concat_identifiers(@identifiers).join(", ") })"
|
409
|
+
end
|
410
|
+
|
411
|
+
def concat_identifiers(ids)
|
412
|
+
return ids.collect {|id| id.kind_of?(String) ? Utils.quoted(id) : id.to_s()}
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
class Utils
|
417
|
+
def Utils.quoted(s)
|
418
|
+
return "\"" + s.gsub("\\", "\\\\").gsub("\"", "\\\"") + "\""
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require '../lib/sahi'
|
3
|
+
|
4
|
+
class TC_MyTest < Test::Unit::TestCase
|
5
|
+
# def setup
|
6
|
+
# end
|
7
|
+
|
8
|
+
# def teardown
|
9
|
+
# end
|
10
|
+
|
11
|
+
def test_to_s_single()
|
12
|
+
assert_equal("_sahi._div(\"id\")", Sahi::ElementStub.new(nil, "div", ["id"]).to_s())
|
13
|
+
assert_equal("_sahi._lastAlert()", Sahi::ElementStub.new(nil, "lastAlert", []).to_s())
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_to_s_multi_strings()
|
17
|
+
assert_equal("_sahi._div(\"id\", \"id2\")", Sahi::ElementStub.new(nil, "div", ["id", "id2"]).to_s())
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_to_s_multi_stubs()
|
21
|
+
stub2 = Sahi::ElementStub.new(nil, "div", ["id2"])
|
22
|
+
near = Sahi::ElementStub.new(nil, "near", [stub2])
|
23
|
+
stub1 = Sahi::ElementStub.new(nil, "div", ["id1", near])
|
24
|
+
assert_equal("_sahi._div(\"id1\", _sahi._near(_sahi._div(\"id2\")))", stub1.to_s())
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_browser_multi_stubs()
|
28
|
+
browser = Sahi::Browser.new("", "", "")
|
29
|
+
assert_equal("_sahi._div(\"id\")", browser.div("id").to_s)
|
30
|
+
assert_equal("_sahi._div(\"id\", \"id2\")", browser.div("id", "id2").to_s())
|
31
|
+
assert_equal("_sahi._div(\"id1\", _sahi._near(_sahi._div(\"id2\")))", browser.div("id1").near(browser.div("id2")).to_s())
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_xy()
|
35
|
+
browser = Sahi::Browser.new("", "", "")
|
36
|
+
assert_equal("_sahi._xy(_sahi._div(\"id\"), 10, 20)", browser.div("id").xy(10, 20).to_s)
|
37
|
+
end
|
38
|
+
end
|
data/test/sahi_test.rb
ADDED
@@ -0,0 +1,391 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require "../lib/sahi"
|
3
|
+
|
4
|
+
class SahiDriverTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@browser = init_browser()
|
7
|
+
@browser.open
|
8
|
+
@base_url = "http://sahi.co.in"
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
if @browser
|
13
|
+
@browser.set_speed(100)
|
14
|
+
@browser.close
|
15
|
+
sleep(1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def init_browser()
|
20
|
+
userdata_dir = "D:/sahi/sf/sahi_993/userdata"
|
21
|
+
browser_path = "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
|
22
|
+
browser_options = "-profile #{userdata_dir}/browser/ff/profiles/sahi0 -no-remote"
|
23
|
+
return Sahi::Browser.new(browser_path, browser_options)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def test1
|
28
|
+
@browser.navigate_to("http://narayan:10000/demo/formTest.htm")
|
29
|
+
@browser.textbox("t1").value = "aaa"
|
30
|
+
@browser.link("Back").click
|
31
|
+
@browser.link("Table Test").click
|
32
|
+
assert_equal("Cell with id", @browser.cell("CellWithId").text)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_ZK
|
36
|
+
@browser.set_speed(200)
|
37
|
+
@browser.navigate_to("http://www.zkoss.org/zkdemo/userguide/")
|
38
|
+
@browser.div("Hello World").click
|
39
|
+
@browser.span("Pure Java").click
|
40
|
+
@browser.div("Various Form").click
|
41
|
+
@browser.wait(5000) {@browser.textbox("z-intbox[1]").visible?}
|
42
|
+
|
43
|
+
@browser.div("Comboboxes").click
|
44
|
+
@browser.textbox("z-combobox-inp").value = "aa"
|
45
|
+
@browser.italic("z-combobox-btn").click
|
46
|
+
@browser.cell("Simple and Rich").click
|
47
|
+
|
48
|
+
@browser.italic("z-combobox-btn[1]").click
|
49
|
+
@browser.span("The coolest technology").click
|
50
|
+
@browser.italic("z-combobox-btn[2]").click
|
51
|
+
@browser.image("CogwheelEye-32x32.gif").click
|
52
|
+
assert(@browser.textbox("z-combobox-inp[2]").exists?)
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def test_fetch()
|
57
|
+
@browser.navigate_to(@base_url + "/demo/formTest.htm")
|
58
|
+
assert_equal(@base_url + "/demo/formTest.htm", @browser.fetch("window.location.href"))
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_accessors()
|
62
|
+
@browser.navigate_to(@base_url + "/demo/formTest.htm")
|
63
|
+
assert_equal("", @browser.textbox("t1").value)
|
64
|
+
assert(@browser.textbox(1).exists?)
|
65
|
+
assert(@browser.textbox("$a_dollar").exists?)
|
66
|
+
@browser.textbox("$a_dollar").value = ("adas")
|
67
|
+
assert_equal("", @browser.textbox(1).value)
|
68
|
+
assert(@browser.textarea("ta1").exists?)
|
69
|
+
assert_equal("", @browser.textarea("ta1").value)
|
70
|
+
assert(@browser.textarea(1).exists?)
|
71
|
+
assert_equal("", @browser.textarea(1).value)
|
72
|
+
assert(@browser.checkbox("c1").exists?)
|
73
|
+
assert_equal("cv1", @browser.checkbox("c1").value)
|
74
|
+
assert(@browser.checkbox(1).exists?)
|
75
|
+
assert_equal("cv2", @browser.checkbox(1).value)
|
76
|
+
assert(@browser.checkbox("c1[1]").exists?)
|
77
|
+
assert_equal("cv3", @browser.checkbox("c1[1]").value)
|
78
|
+
assert(@browser.checkbox(3).exists?)
|
79
|
+
assert_equal("", @browser.checkbox(3).value)
|
80
|
+
assert(@browser.radio("r1").exists?)
|
81
|
+
assert_equal("rv1", @browser.radio("r1").value)
|
82
|
+
assert(@browser.password("p1").exists?)
|
83
|
+
assert_equal("", @browser.password("p1").value)
|
84
|
+
assert(@browser.password(1).exists?)
|
85
|
+
assert_equal("", @browser.password(1).value)
|
86
|
+
assert(@browser.select("s1").exists?)
|
87
|
+
assert_equal("o1", @browser.select("s1").selected_text())
|
88
|
+
assert(@browser.select("s1Id[1]").exists?)
|
89
|
+
assert_equal("o1", @browser.select("s1Id[1]").selected_text())
|
90
|
+
assert(@browser.select(2).exists?)
|
91
|
+
assert_equal("o1", @browser.select(2).selected_text())
|
92
|
+
assert(@browser.button("button value").exists?)
|
93
|
+
assert(@browser.button("btnName[1]").exists?)
|
94
|
+
assert(@browser.button("btnId[2]").exists?)
|
95
|
+
assert(@browser.button(3).exists?)
|
96
|
+
assert(@browser.submit("Add").exists?)
|
97
|
+
assert(@browser.submit("submitBtnName[1]").exists?)
|
98
|
+
assert(@browser.submit("submitBtnId[2]").exists?)
|
99
|
+
assert(@browser.submit(3).exists?)
|
100
|
+
assert(@browser.image("imageAlt1").exists?)
|
101
|
+
assert(@browser.image("imageId1[1]").exists?)
|
102
|
+
assert(@browser.image(2).exists?)
|
103
|
+
assert(!@browser.link("Back22").exists?)
|
104
|
+
assert(@browser.link("Back").exists?)
|
105
|
+
assert(@browser.accessor("document.getElementById('s1Id')").exists?)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_select()
|
109
|
+
@browser.navigate_to(@base_url + "/demo/formTest.htm")
|
110
|
+
assert_equal("o1", @browser.select("s1Id[1]").selected_text())
|
111
|
+
@browser.select("s1Id[1]").choose("o2")
|
112
|
+
assert_equal("o2", @browser.select("s1Id[1]").selected_text())
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_set_file()
|
116
|
+
@browser.navigate_to(@base_url + "/demo/php/fileUpload.htm")
|
117
|
+
@browser.file("file").file = "D:/sahi/sf/sahi_993/userdata/scripts/demo/uploadme.txt";
|
118
|
+
@browser.submit("Submit Single").click;
|
119
|
+
assert(@browser.span("size").exists?)
|
120
|
+
assert_not_nil(@browser.span("size").text().index("0.3046875 Kb"))
|
121
|
+
assert_not_nil(@browser.span("type").text().index("Single"))
|
122
|
+
@browser.link("Back to form").click;
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_multi_file_upload()
|
126
|
+
@browser.navigate_to(@base_url + "/demo/php/fileUpload.htm")
|
127
|
+
@browser.file("file[]").file = "D:/sahi/sf/sahi_993/userdata/scripts/demo/uploadme.txt";
|
128
|
+
@browser.file("file[]").file = "D:/sahi/sf/sahi_993/userdata/scripts/demo/uploadme2.txt";
|
129
|
+
@browser.submit("Submit Array").click;
|
130
|
+
assert_not_nil(@browser.span("type").text().index("Array"))
|
131
|
+
assert_not_nil(@browser.span("file").text().index("uploadme.txt"))
|
132
|
+
assert_not_nil(@browser.span("size").text().index("0.3046875 Kb"))
|
133
|
+
|
134
|
+
assert_not_nil(@browser.span("file[1]").text().index("uploadme2.txt"))
|
135
|
+
assert_not_nil(@browser.span("size[1]").text().index("0.32421875 Kb"))
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_clicks()
|
139
|
+
@browser.navigate_to(@base_url + "/demo/formTest.htm")
|
140
|
+
assert_not_nil(@browser.checkbox("c1"))
|
141
|
+
@browser.checkbox("c1").click;
|
142
|
+
assert_equal("true", @browser.checkbox("c1").fetch("checked"))
|
143
|
+
@browser.checkbox("c1").click;
|
144
|
+
assert_equal("false", @browser.checkbox("c1").fetch("checked"))
|
145
|
+
|
146
|
+
assert_not_nil(@browser.radio("r1"))
|
147
|
+
@browser.radio("r1").click;
|
148
|
+
assert_equal("true", @browser.radio("r1").fetch("checked"))
|
149
|
+
assert(@browser.radio("r1").checked())
|
150
|
+
assert(!@browser.radio("r1[1]").checked())
|
151
|
+
@browser.radio("r1[1]").click;
|
152
|
+
assert_equal("false", @browser.radio("r1").fetch("checked"))
|
153
|
+
assert(@browser.radio("r1[1]").checked())
|
154
|
+
assert(!@browser.radio("r1").checked())
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_links()
|
158
|
+
@browser.navigate_to(@base_url + "/demo/index.htm")
|
159
|
+
@browser.link("Link Test").click;
|
160
|
+
@browser.link("linkByContent").click;
|
161
|
+
@browser.link("Back").click;
|
162
|
+
@browser.link("link with return true").click;
|
163
|
+
assert(@browser.textarea("ta1").exists?)
|
164
|
+
assert_equal("", @browser.textarea("ta1").value)
|
165
|
+
@browser.link("Back").click;
|
166
|
+
@browser.link("Link Test").click;
|
167
|
+
@browser.link("link with return false").click;
|
168
|
+
assert(@browser.textbox("t1").exists?)
|
169
|
+
assert_equal("formTest link with return false", @browser.textbox("t1").value)
|
170
|
+
assert(@browser.link("linkByContent").exists?)
|
171
|
+
|
172
|
+
@browser.link("link with returnValue=false").click;
|
173
|
+
assert(@browser.textbox("t1").exists?)
|
174
|
+
assert_equal("formTest link with returnValue=false", @browser.textbox("t1").value)
|
175
|
+
@browser.link("added handler using js").click;
|
176
|
+
assert(@browser.textbox("t1").exists?)
|
177
|
+
assert_equal("myFn called", @browser.textbox("t1").value)
|
178
|
+
@browser.textbox("t1").value = ("")
|
179
|
+
@browser.image("imgWithLink").click;
|
180
|
+
@browser.link("Link Test").click;
|
181
|
+
@browser.image("imgWithLinkNoClick").click;
|
182
|
+
assert(@browser.textbox("t1").exists?)
|
183
|
+
assert_equal("myFn called", @browser.textbox("t1").value)
|
184
|
+
@browser.link("Back").click;
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def test_popup_title_name_mix()
|
189
|
+
@browser.navigate_to(@base_url + "/demo/index.htm")
|
190
|
+
@browser.link("Window Open Test").click;
|
191
|
+
@browser.link("Window Open Test With Title").click;
|
192
|
+
@browser.link("Table Test").click;
|
193
|
+
|
194
|
+
popup_popwin = @browser.popup("popWin")
|
195
|
+
|
196
|
+
popup_popwin.link("Link Test").click;
|
197
|
+
@browser.link("Back").click;
|
198
|
+
|
199
|
+
popup_with_title = @browser.popup("With Title")
|
200
|
+
|
201
|
+
popup_with_title.link("Form Test").click;
|
202
|
+
@browser.link("Table Test").click;
|
203
|
+
popup_with_title.textbox("t1").value = ("d")
|
204
|
+
@browser.link("Back").click;
|
205
|
+
popup_with_title.textbox(1).value = ("e")
|
206
|
+
@browser.link("Table Test").click;
|
207
|
+
popup_with_title.textbox("name").value = ("f")
|
208
|
+
assert_not_nil(popup_popwin.link("linkByHtml").exists?)
|
209
|
+
|
210
|
+
assert_not_nil(@browser.cell("CellWithId"))
|
211
|
+
assert_equal("Cell with id", @browser.cell("CellWithId").text)
|
212
|
+
popup_with_title.link("Break Frames").click;
|
213
|
+
|
214
|
+
popupSahiTests = @browser.popup("Sahi Tests")
|
215
|
+
popupSahiTests.close()
|
216
|
+
|
217
|
+
popup_popwin.link("Break Frames").click;
|
218
|
+
popup_popwin.close()
|
219
|
+
@browser.link("Back").click;
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
def test_in()
|
224
|
+
@browser.navigate_to(@base_url + "/demo/tableTest.htm")
|
225
|
+
assert_equal("111", @browser.textarea("ta").near(@browser.cell("a1")).value)
|
226
|
+
assert_equal("222", @browser.textarea("ta").near(@browser.cell("a2")).value)
|
227
|
+
@browser.link("Go back").in(@browser.cell("a1").parent_node()).click;
|
228
|
+
assert(@browser.link("Link Test").exists?)
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_exists()
|
232
|
+
@browser.navigate_to(@base_url + "/demo/index.htm")
|
233
|
+
assert(@browser.link("Link Test").exists?)
|
234
|
+
assert(!@browser.link("Link Test NonExistent").exists?)
|
235
|
+
end
|
236
|
+
|
237
|
+
def alert1(message)
|
238
|
+
@browser.navigate_to(@base_url + "/demo/alertTest.htm")
|
239
|
+
@browser.textbox("t1").value = ("Message " + message)
|
240
|
+
@browser.button("Click For Alert").click;
|
241
|
+
@browser.navigate_to("/demo/alertTest.htm")
|
242
|
+
sleep(1)
|
243
|
+
assert_equal("Message " + message, @browser.last_alert())
|
244
|
+
@browser.clear_last_alert()
|
245
|
+
assert_nil(@browser.last_alert())
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_alert()
|
249
|
+
alert1("One")
|
250
|
+
alert1("Two")
|
251
|
+
alert1("Three")
|
252
|
+
@browser.button("Click For Multiline Alert").click;
|
253
|
+
assert_equal("You must correct the following Errors:\nYou must select a messaging price plan.\nYou must select an international messaging price plan.\nYou must enter a value for the Network Lookup Charge", @browser.last_alert())
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_confirm()
|
257
|
+
@browser.navigate_to(@base_url + "/demo/confirmTest.htm")
|
258
|
+
@browser.expect_confirm("Some question?", true)
|
259
|
+
@browser.button("Click For Confirm").click;
|
260
|
+
assert_equal("oked", @browser.textbox("t1").value)
|
261
|
+
@browser.navigate_to("/demo/confirmTest.htm")
|
262
|
+
sleep(1)
|
263
|
+
assert_equal("Some question?", @browser.last_confirm())
|
264
|
+
@browser.clear_last_confirm()
|
265
|
+
assert_nil(@browser.last_confirm())
|
266
|
+
|
267
|
+
@browser.expect_confirm("Some question?", false)
|
268
|
+
@browser.button("Click For Confirm").click;
|
269
|
+
assert_equal("canceled", @browser.textbox("t1").value)
|
270
|
+
assert_equal("Some question?", @browser.last_confirm())
|
271
|
+
@browser.clear_last_confirm()
|
272
|
+
assert_nil(@browser.last_confirm())
|
273
|
+
|
274
|
+
@browser.expect_confirm("Some question?", true)
|
275
|
+
@browser.button("Click For Confirm").click;
|
276
|
+
assert_equal("oked", @browser.textbox("t1").value)
|
277
|
+
assert_equal("Some question?", @browser.last_confirm())
|
278
|
+
@browser.clear_last_confirm()
|
279
|
+
assert_nil(@browser.last_confirm())
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_prompt()
|
283
|
+
@browser.navigate_to(@base_url + "/demo/promptTest.htm")
|
284
|
+
@browser.expect_prompt("Some prompt?", "abc")
|
285
|
+
@browser.button("Click For Prompt").click;
|
286
|
+
assert_not_nil(@browser.textbox("t1"))
|
287
|
+
assert_equal("abc", @browser.textbox("t1").value)
|
288
|
+
@browser.navigate_to("/demo/promptTest.htm")
|
289
|
+
@browser.waitFor(2000)
|
290
|
+
assert_equal("Some prompt?", @browser.last_prompt())
|
291
|
+
@browser.clear_last_prompt()
|
292
|
+
assert_nil(@browser.last_prompt())
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
def test_visible
|
297
|
+
@browser.navigate_to(@base_url + "/demo/index.htm")
|
298
|
+
@browser.link("Visible Test").click;
|
299
|
+
assert(@browser.spandiv("using display").visible?)
|
300
|
+
|
301
|
+
@browser.button("Display none").click;
|
302
|
+
assert(!@browser.spandiv("using display").visible?)
|
303
|
+
@browser.button("Display block").click;
|
304
|
+
assert(@browser.spandiv("using display").visible?)
|
305
|
+
|
306
|
+
@browser.button("Display none").click;
|
307
|
+
assert(!@browser.spandiv("using display").visible?)
|
308
|
+
@browser.button("Display inline").click;
|
309
|
+
assert(@browser.spandiv("using display").visible?)
|
310
|
+
|
311
|
+
assert(@browser.spandiv("using visibility").visible?)
|
312
|
+
@browser.button("Visibility hidden").click;
|
313
|
+
assert(!@browser.spandiv("using visibility").visible?)
|
314
|
+
@browser.button("Visibility visible").click;
|
315
|
+
assert(@browser.spandiv("using visibility").visible?)
|
316
|
+
|
317
|
+
assert(!@browser.byId("nestedBlockInNone").visible?)
|
318
|
+
assert(!@browser.byId("absoluteNestedBlockInNone").visible?)
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_check()
|
322
|
+
@browser.navigate_to(@base_url + "/demo/")
|
323
|
+
@browser.link("Form Test").click;
|
324
|
+
assert_equal("false", @browser.checkbox("c1").fetch("checked"))
|
325
|
+
assert(!@browser.checkbox("c1").checked())
|
326
|
+
@browser.checkbox("c1").check()
|
327
|
+
assert_equal("true", @browser.checkbox("c1").fetch("checked"))
|
328
|
+
assert(@browser.checkbox("c1").checked())
|
329
|
+
@browser.checkbox("c1").check()
|
330
|
+
assert_equal("true", @browser.checkbox("c1").fetch("checked"))
|
331
|
+
@browser.checkbox("c1").uncheck()
|
332
|
+
assert_equal("false", @browser.checkbox("c1").fetch("checked"))
|
333
|
+
@browser.checkbox("c1").uncheck()
|
334
|
+
assert_equal("false", @browser.checkbox("c1").fetch("checked"))
|
335
|
+
@browser.checkbox("c1").click;
|
336
|
+
assert_equal("true", @browser.checkbox("c1").fetch("checked"))
|
337
|
+
end
|
338
|
+
|
339
|
+
def test_focus()
|
340
|
+
@browser.navigate_to(@base_url + "/demo/focusTest.htm")
|
341
|
+
@browser.textbox("t2").focus()
|
342
|
+
assert_equal("focused", @browser.textbox("t1").value)
|
343
|
+
@browser.textbox("t2").remove_focus()
|
344
|
+
assert_equal("not focused", @browser.textbox("t1").value)
|
345
|
+
@browser.textbox("t2").focus()
|
346
|
+
assert_equal("focused", @browser.textbox("t1").value)
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_title()
|
350
|
+
@browser.navigate_to(@base_url + "/demo/index.htm")
|
351
|
+
assert_equal("Sahi Tests", @browser.title)
|
352
|
+
@browser.link("Form Test").click;
|
353
|
+
assert_equal("Form Test", @browser.title)
|
354
|
+
@browser.link("Back").click;
|
355
|
+
@browser.link("Window Open Test With Title").click;
|
356
|
+
assert_equal("With Title", @browser.popup("With Title").title)
|
357
|
+
end
|
358
|
+
|
359
|
+
def test_area()
|
360
|
+
@browser.navigate_to(@base_url + "/demo/map.htm")
|
361
|
+
@browser.navigate_to("map.htm")
|
362
|
+
assert(@browser.area("Record").exists?)
|
363
|
+
assert(@browser.area("Playback").exists?)
|
364
|
+
assert(@browser.area("Info").exists?)
|
365
|
+
assert(@browser.area("Circular").exists?)
|
366
|
+
@browser.area("Record").mouse_over()
|
367
|
+
assert_equal("Record", @browser.div("output").text)
|
368
|
+
@browser.button("Clear").mouse_over()
|
369
|
+
assert_equal("", @browser.div("output").text)
|
370
|
+
@browser.area("Record").click;
|
371
|
+
assert(@browser.link("linkByContent").exists?)
|
372
|
+
#@browser.navigate_to("map.htm")
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_dragdrop()
|
376
|
+
@browser.navigate_to("http://www.snook.ca/technical/mootoolsdragdrop/")
|
377
|
+
@browser.div("Drag me").dragAndDropOn(@browser.div("Item 2"))
|
378
|
+
assert @browser.div("dropped").exists?
|
379
|
+
assert @browser.div("Item 1").exists?
|
380
|
+
assert @browser.div("Item 3").exists?
|
381
|
+
assert @browser.div("Item 4").exists?
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_wait()
|
385
|
+
@browser.navigate_to(@base_url + "/demo/waitCondition1.htm")
|
386
|
+
@browser.wait(15) {"populated" == @browser.textbox("t1").value}
|
387
|
+
assert_equal("populated", @browser.textbox("t1").value)
|
388
|
+
end
|
389
|
+
|
390
|
+
end
|
391
|
+
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sahi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Narayan Raman
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-21 00:00:00 +05:30
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: Platform
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 3
|
30
|
+
- 9
|
31
|
+
version: 0.3.9
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: guid
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 1
|
44
|
+
- 1
|
45
|
+
version: 0.1.1
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
description: Ruby driver for Sahi. Sahi is a web automation tool. Sahi runs as a proxy, and the browser needs to configured to use Sahi's proxy. The browser can then be driven via the Sahi ruby driver.
|
49
|
+
email: support@sahi.co.in
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files:
|
55
|
+
- README.txt
|
56
|
+
files:
|
57
|
+
- lib/sahi.rb
|
58
|
+
- README.txt
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://sahi.co.in/w/ruby/
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message: Welcome to easy web automation using Sahi. You need to have Sahi proxy running before using this driver.
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.3.6
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Ruby driver for Sahi - automation tool for web applications
|
89
|
+
test_files:
|
90
|
+
- test/elementstub_test.rb
|
91
|
+
- test/sahi_test.rb
|