caius-safariwatir 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,46 @@
1
+ = SafariWatir
2
+
3
+ * http://safariwatir.rubyforge.org
4
+ * http://rubyforge.org/mailman/listinfo/safariwatir-general
5
+ * http://twitter.com/SafariWatir
6
+
7
+ == DESCRIPTION:
8
+
9
+ We are putting Watir on Safari.
10
+ The original Watir (Web Application Testing in Ruby) project supports only IE on Windows.
11
+ This project aims at adding Watir support for Safari on the Mac.
12
+
13
+ == Requirements
14
+
15
+ Mac OS X running Safari. Some features require you to turn on "Enable access for assistive devices" in System Preferences > Universal Access.
16
+
17
+
18
+ == SYNOPSIS:
19
+
20
+ require 'rubygems'
21
+ require 'safariwatir'
22
+
23
+ browser = Watir::Safari.new
24
+ browser.goto("http://google.com")
25
+ browser.text_field(:name, "q").set("obtiva")
26
+ browser.button(:name, "btnI").click
27
+ puts "FAILURE" unless browser.contains_text("software")
28
+
29
+ == INSTALL:
30
+
31
+ [sudo] gem install safariwatir
32
+
33
+ or
34
+
35
+ git clone git://github.com/redsquirrel/safariwatir.git
36
+ cd safariwatir
37
+ rake install
38
+
39
+ == RUNNING SAFARIWATIR AGAINST WATIR'S CORE TESTS
40
+
41
+ # First, install the SafariWatir gem (see above)
42
+ svn checkout https://svn.openqa.org/svn/watir/trunk
43
+ cd trunk/watir
44
+ cp unittests/options.yml.example unittests/options.yml
45
+ # Edit unittests/options.yml and set browser: safari
46
+ ruby unittests/core_tests.rb
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('safariwatir', '0.3.4') do | config |
6
+ config.summary = %q{Automated testing tool for web applications.}
7
+ config.description = %q{WATIR stands for "Web Application Testing in Ruby". See WATIR project for more information. This is a Safari-version of the original IE-only WATIR.}
8
+ config.url = 'http://safariwatir.rubyforge.org/'
9
+ config.author = 'Dave Hoover'
10
+ config.email = 'dave@obtiva.com'
11
+ config.ignore_pattern = ['tmp/*', 'script/*']
12
+ config.development_dependencies = ["rb-appscript"]
13
+ end
@@ -0,0 +1,541 @@
1
+ require 'watir/exceptions'
2
+ require 'safariwatir/scripter'
3
+ require 'safariwatir/core_ext'
4
+
5
+ module Watir
6
+ include Watir::Exception
7
+
8
+ module PageContainer
9
+ def html
10
+ @scripter.document_html
11
+ end
12
+
13
+ def text
14
+ @scripter.document_text
15
+ end
16
+
17
+ def title
18
+ @scripter.document_title
19
+ end
20
+ end
21
+
22
+ module Container
23
+ attr_reader :scripter
24
+ private :scripter
25
+
26
+ DEFAULT_TYPING_LAG = 0.08
27
+
28
+ def set_fast_speed
29
+ @scripter.typing_lag = 0
30
+ end
31
+
32
+ def set_slow_speed
33
+ @scripter.typing_lag = DEFAULT_TYPING_LAG
34
+ end
35
+
36
+ def speed=(how_fast)
37
+ case how_fast
38
+ when :fast : set_fast_speed
39
+ when :slow : set_slow_speed
40
+ else
41
+ raise ArgumentError, "Invalid speed: #{how_fast}"
42
+ end
43
+ end
44
+
45
+ module Clickable
46
+ def click
47
+ @scripter.highlight(self) do
48
+ click_element
49
+ end
50
+ end
51
+ end
52
+
53
+ class AlertWindow
54
+ def_init :scripter
55
+
56
+ def click
57
+ @scripter.click_alert
58
+ end
59
+ end
60
+
61
+ class SecurityWarningWindow
62
+ def initialize(scripter, url)
63
+ @scripter = scripter
64
+ @url = url
65
+ end
66
+
67
+ def continue
68
+ handle_click("Continue")
69
+ end
70
+
71
+ def cancel
72
+ handle_click("Cancel")
73
+ end
74
+
75
+ private
76
+ def handle_click(button)
77
+ if @url
78
+ @scripter.navigate_to(@url) do
79
+ @scripter.click_security_warning(button)
80
+ end
81
+ else
82
+ @scripter.click_security_warning(button)
83
+ end
84
+ end
85
+ end
86
+
87
+ class Frame
88
+ include Container
89
+ include PageContainer
90
+
91
+ attr_reader :name
92
+
93
+ def initialize(scripter, name)
94
+ @name = name
95
+ @scripter = scripter.for_frame(self)
96
+ end
97
+ end
98
+
99
+ class HtmlElement
100
+ def_init :scripter, :how, :what
101
+ attr_reader :how, :what
102
+
103
+ # overridden in derivitives
104
+ def tag
105
+ raise RuntimeError, "tag not provided for #{name}"
106
+ end
107
+
108
+ # overridden in derivitives
109
+ def speak
110
+ @scripter.speak("#{name}'s don't know how to speak.")
111
+ end
112
+
113
+ def exists?
114
+ @scripter.element_exists?(self)
115
+ end
116
+ alias :exist? :exists?
117
+
118
+ def name
119
+ self.class.name.split("::").last
120
+ end
121
+
122
+ def operate(&block)
123
+ scripter_suffix = OPERATIONS[how]
124
+ if scripter_suffix.kind_of? Hash
125
+ scripter_suffix = scripter_suffix[name]
126
+ end
127
+ if scripter_suffix.nil?
128
+ raise "SafariWatir does not currently support finding by #{how}"
129
+ end
130
+ @scripter.send("operate_#{scripter_suffix}", self, &block)
131
+ end
132
+
133
+ OPERATIONS = {
134
+ :id => "by_id",
135
+ :index => "by_index",
136
+ :class => "by_class",
137
+ :name => "by_name",
138
+ :text => { "Link" => "on_link", "Label" => "by_text" },
139
+ :url => "on_link",
140
+ :value => "by_input_value",
141
+ :caption => "by_input_value",
142
+ :src => "by_src",
143
+ }
144
+ end
145
+
146
+ class Form < HtmlElement
147
+ def_init :scripter, :how, :what
148
+
149
+ def submit
150
+ @scripter.submit_form(self)
151
+ end
152
+
153
+ def tag; "FORM"; end
154
+ end
155
+
156
+ class InputElement < HtmlElement
157
+ include Clickable
158
+
159
+ def speak
160
+ @scripter.speak_value_of(self)
161
+ end
162
+
163
+ def tag; "INPUT"; end
164
+
165
+ # Hook for derivitives
166
+ def by_value; end
167
+ end
168
+
169
+ class ContentElement < HtmlElement
170
+ include Clickable
171
+ include Container
172
+
173
+ def html
174
+ @scripter.get_html_for(self)
175
+ end
176
+
177
+ def text
178
+ @scripter.get_text_for(self)
179
+ end
180
+
181
+ def speak
182
+ @scripter.speak_text_of(self)
183
+ end
184
+ end
185
+
186
+ class Image < HtmlElement
187
+ include Clickable
188
+
189
+ def tag; "IMG"; end
190
+ end
191
+
192
+ class Button < InputElement
193
+ end
194
+
195
+ class Checkbox < InputElement
196
+ def_init :scripter, :how, :what, :value
197
+
198
+ def by_value
199
+ @value
200
+ end
201
+
202
+ # Contributed by Kyle Campos
203
+ def checked?
204
+ @scripter.checkbox_is_checked?(self)
205
+ end
206
+
207
+ def set(check_it = true)
208
+ return if check_it && checked?
209
+ return if !check_it && !checked?
210
+ click
211
+ end
212
+ end
213
+
214
+ class Div < ContentElement
215
+ def tag; "DIV"; end
216
+ end
217
+
218
+ class Label < ContentElement
219
+ def tag; "LABEL"; end
220
+ end
221
+
222
+ class Link < ContentElement
223
+ def click
224
+ @scripter.highlight(self) do
225
+ click_link
226
+ end
227
+ end
228
+
229
+ def tag; "A"; end
230
+ end
231
+
232
+ class Radio < Checkbox
233
+ end
234
+
235
+ class SelectList < InputElement
236
+ def select(label)
237
+ option(:text, label).select
238
+ end
239
+
240
+ def select_value(value)
241
+ option(:value, value).select
242
+ end
243
+
244
+ def option(how, what)
245
+ Option.new(@scripter, self, how, what)
246
+ end
247
+
248
+ def selected_values
249
+ values = []
250
+ index = 1
251
+ loop do
252
+ option = option(:index, index)
253
+ break unless option.exists?
254
+ values << option if option.selected?
255
+ index += 1
256
+ end
257
+ values.map {|o| o.text } #TODO?
258
+ end
259
+
260
+ def selected_value
261
+ selected_values.first
262
+ end
263
+
264
+ def speak
265
+ @scripter.speak_options_for(self)
266
+ end
267
+
268
+ def tag; "SELECT"; end
269
+ end
270
+
271
+ class Option < InputElement
272
+ def_init :scripter, :select_list, :how, :what
273
+
274
+ def select
275
+ @scripter.highlight(self) do
276
+ select_option
277
+ end
278
+ end
279
+
280
+ def operate(&block)
281
+ @select_list.operate(&block)
282
+ end
283
+
284
+ def exists?
285
+ @scripter.option_exists?(self)
286
+ end
287
+ alias :exist? :exists?
288
+
289
+ def selected?
290
+ @scripter.option_selected?(self)
291
+ end
292
+
293
+ def text
294
+ @scripter.get_text_for(self)
295
+ end
296
+
297
+ def tag; "OPTION"; end
298
+ end
299
+
300
+ class Span < ContentElement
301
+ def tag; "SPAN"; end
302
+ end
303
+
304
+ class Table
305
+ def_init :scripter, :how, :what
306
+ attr_reader :how, :what
307
+
308
+ def each
309
+ # TODO
310
+ end
311
+
312
+ def [](index)
313
+ TableRow.new(@scripter, :index, index, self)
314
+ end
315
+
316
+ def row_count
317
+ # TODO
318
+ end
319
+
320
+ def column_count
321
+ # TODO
322
+ end
323
+
324
+ def tag; "TABLE"; end
325
+ end
326
+
327
+ class TableRow
328
+ def initialize(scripter, how, what, table = nil)
329
+ @scripter = scripter
330
+ @how = how
331
+ @what = what
332
+ @table = table
333
+ end
334
+
335
+ attr_reader :table, :how, :what
336
+
337
+ def each
338
+ # TODO
339
+ end
340
+
341
+ def [](index)
342
+ TableCell.new(@scripter, :index, index, self)
343
+ end
344
+
345
+ def column_count
346
+ # TODO
347
+ end
348
+
349
+ def tag; "TR"; end
350
+ end
351
+
352
+ class TableCell < ContentElement
353
+ def initialize(scripter, how, what, row = nil)
354
+ @scripter = scripter.for_table(self)
355
+ set_slow_speed # TODO: Need to inherit this somehow
356
+
357
+ @how = how
358
+ @what = what
359
+ @row = row
360
+ end
361
+
362
+ attr_reader :how, :what, :row
363
+
364
+ def operate(&block)
365
+ @scripter.operate_by_table_cell(self, &block)
366
+ end
367
+
368
+ def tag; "TD"; end
369
+ end
370
+
371
+ class TextField < InputElement
372
+ def set(value)
373
+ value = value.to_s
374
+ @scripter.focus(self)
375
+ @scripter.highlight(self) do
376
+ clear_text_input
377
+ value.length.times do |i|
378
+ append_text_input(value[i, 1])
379
+ end
380
+ end
381
+ @scripter.blur(self)
382
+ end
383
+
384
+ def getContents
385
+ @scripter.get_value_for(self)
386
+ end
387
+
388
+ def verify_contains(expected)
389
+ actual = getContents
390
+ case expected
391
+ when Regexp
392
+ actual.match(expected) != nil
393
+ else
394
+ expected == actual
395
+ end
396
+ end
397
+ end
398
+
399
+ class Password < TextField
400
+ end
401
+
402
+
403
+ # Elements
404
+
405
+ def button(how, what)
406
+ Button.new(scripter, how, what)
407
+ end
408
+
409
+ def cell(how, what)
410
+ TableCell.new(scripter, how, what)
411
+ end
412
+
413
+ def checkbox(how, what, value = nil)
414
+ Checkbox.new(scripter, how, what, value)
415
+ end
416
+
417
+ def div(how, what)
418
+ Div.new(scripter, how, what)
419
+ end
420
+
421
+ def form(how, what)
422
+ Form.new(scripter, how, what)
423
+ end
424
+
425
+ def frame(name)
426
+ Frame.new(scripter, name)
427
+ end
428
+
429
+ def image(how, what)
430
+ Image.new(scripter, how, what)
431
+ end
432
+
433
+ def label(how, what)
434
+ Label.new(scripter, how, what)
435
+ end
436
+
437
+ def link(how, what)
438
+ Link.new(scripter, how, what)
439
+ end
440
+
441
+ def password(how, what)
442
+ Password.new(scripter, how, what)
443
+ end
444
+
445
+ def radio(how, what, value = nil)
446
+ Radio.new(scripter, how, what, value)
447
+ end
448
+
449
+ def row(how, what)
450
+ TableRow.new(scripter, how, what)
451
+ end
452
+
453
+ def select_list(how, what)
454
+ SelectList.new(scripter, how, what)
455
+ end
456
+
457
+ def span(how, what)
458
+ Span.new(scripter, how, what)
459
+ end
460
+
461
+ def table(how, what)
462
+ Table.new(scripter, how, what)
463
+ end
464
+
465
+ def text_field(how, what)
466
+ TextField.new(scripter, how, what)
467
+ end
468
+
469
+ def contains_text(what)
470
+ case what
471
+ when Regexp:
472
+ text =~ what
473
+ when String:
474
+ text.index(what)
475
+ else
476
+ raise MissingWayOfFindingObjectException
477
+ end
478
+ end
479
+ end
480
+
481
+ class Safari
482
+ include Container
483
+ include PageContainer
484
+
485
+ def self.start(url = nil)
486
+ safari = new
487
+ safari.goto(url) if url
488
+ safari
489
+ end
490
+
491
+ def initialize
492
+ @scripter = AppleScripter.new(JavaScripter.new)
493
+ @scripter.ensure_window_ready
494
+ set_slow_speed
495
+ end
496
+
497
+ # URL of page
498
+ def url
499
+ scripter.url
500
+ end
501
+
502
+ def close
503
+ scripter.close
504
+ end
505
+
506
+ def quit
507
+ scripter.quit
508
+ end
509
+
510
+ def alert
511
+ AlertWindow.new(scripter)
512
+ end
513
+
514
+ def security_warning
515
+ SecurityWarningWindow.new(scripter)
516
+ end
517
+
518
+ def security_warning_at(url)
519
+ SecurityWarningWindow.new(scripter, url)
520
+ end
521
+
522
+ def goto(url)
523
+ scripter.navigate_to(url)
524
+ end
525
+
526
+ # Reloads the page
527
+ def reload
528
+ scripter.reload
529
+ end
530
+ end # class Safari
531
+
532
+
533
+ class WebKit < Safari
534
+ def initialize
535
+ @scripter = AppleScripter.new(JavaScripter.new,:appname => "WebKit")
536
+ @scripter.ensure_window_ready
537
+ set_slow_speed
538
+ end
539
+ end # class WebKit
540
+
541
+ end