mpeychich-safariwatir 0.3.6

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.
@@ -0,0 +1,49 @@
1
+ "There's something eerily tingly about seeing a browser run by itself."
2
+ http://twitter.com/swombat/status/1280692921
3
+
4
+ = SafariWatir
5
+
6
+ * http://safariwatir.rubyforge.org
7
+ * http://rubyforge.org/mailman/listinfo/safariwatir-general
8
+ * http://twitter.com/SafariWatir
9
+
10
+ == DESCRIPTION:
11
+
12
+ We are putting Watir on Safari.
13
+ The original Watir (Web Application Testing in Ruby) project supports only IE on Windows.
14
+ This project aims at adding Watir support for Safari on the Mac.
15
+
16
+ == Requirements
17
+
18
+ Mac OS X running Safari. Some features require you to turn on "Enable access for assistive devices" in System Preferences > Universal Access.
19
+
20
+
21
+ == SYNOPSIS:
22
+
23
+ require 'rubygems'
24
+ require 'safariwatir'
25
+
26
+ browser = Watir::Safari.new
27
+ browser.goto("http://google.com")
28
+ browser.text_field(:name, "q").set("obtiva")
29
+ browser.button(:name, "btnI").click
30
+ puts "FAILURE" unless browser.contains_text("software")
31
+
32
+ == INSTALL:
33
+
34
+ [sudo] gem install safariwatir
35
+
36
+ or
37
+
38
+ git clone git://github.com/redsquirrel/safariwatir.git
39
+ cd safariwatir
40
+ rake install
41
+
42
+ == RUNNING SAFARIWATIR AGAINST WATIR'S CORE TESTS
43
+
44
+ # First, install the SafariWatir gem (see above)
45
+ svn checkout https://svn.openqa.org/svn/watir/trunk
46
+ cd trunk/watir
47
+ cp unittests/options.yml.example unittests/options.yml
48
+ # Edit unittests/options.yml and set browser: safari
49
+ ruby unittests/core_tests.rb
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('safariwatir', '0.3.5') 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 => {
139
+ "Link" => "on_link",
140
+ "Label" => "by_text",
141
+ 'BasicTagFinder' => 'by_text'
142
+ },
143
+ :url => "on_link",
144
+ :value => "by_input_value",
145
+ :caption => "by_input_value",
146
+ :src => "by_src",
147
+ }
148
+ end
149
+
150
+ class Form < HtmlElement
151
+ def_init :scripter, :how, :what
152
+
153
+ def submit
154
+ @scripter.submit_form(self)
155
+ end
156
+
157
+ def tag; "FORM"; end
158
+ end
159
+
160
+ class InputElement < HtmlElement
161
+ include Clickable
162
+
163
+ def speak
164
+ @scripter.speak_value_of(self)
165
+ end
166
+
167
+ def enabled?
168
+ !@scripter.element_disabled?(self)
169
+ end
170
+
171
+ def tag; "INPUT"; end
172
+
173
+ # Hook for derivitives
174
+ def by_value; end
175
+ end
176
+
177
+ class ContentElement < HtmlElement
178
+ include Clickable
179
+ include Container
180
+
181
+ def html
182
+ @scripter.get_html_for(self)
183
+ end
184
+
185
+ def text
186
+ @scripter.get_text_for(self)
187
+ end
188
+
189
+ def speak
190
+ @scripter.speak_text_of(self)
191
+ end
192
+ end
193
+
194
+ class Image < HtmlElement
195
+ include Clickable
196
+
197
+ def tag; "IMG"; end
198
+ end
199
+
200
+ class Button < InputElement
201
+ end
202
+
203
+ class Checkbox < InputElement
204
+ def_init :scripter, :how, :what, :value
205
+
206
+ def by_value
207
+ @value
208
+ end
209
+
210
+ # Contributed by Kyle Campos
211
+ def checked?
212
+ @scripter.checkbox_is_checked?(self)
213
+ end
214
+
215
+ def set(check_it = true)
216
+ return if check_it && checked?
217
+ return if !check_it && !checked?
218
+ click
219
+ end
220
+ end
221
+
222
+ class BasicContentElement < ContentElement
223
+ def_init :scripter, :tag, :how, :what
224
+ def tag; @tag.to_s.upcase; end
225
+ end
226
+
227
+ class Link < ContentElement
228
+ def click
229
+ @scripter.highlight(self) do
230
+ click_link
231
+ end
232
+ end
233
+
234
+ def tag; "A"; end
235
+ end
236
+
237
+ class Radio < Checkbox
238
+ end
239
+
240
+ class SelectList < InputElement
241
+ def select(label)
242
+ option(:text, label).select
243
+ end
244
+
245
+ def select_value(value)
246
+ option(:value, value).select
247
+ end
248
+
249
+ def option(how, what)
250
+ Option.new(@scripter, self, how, what)
251
+ end
252
+
253
+ def selected_values
254
+ values = []
255
+ index = 1
256
+ loop do
257
+ option = option(:index, index)
258
+ break unless option.exists?
259
+ values << option if option.selected?
260
+ index += 1
261
+ end
262
+ values.map {|o| o.text } #TODO?
263
+ end
264
+
265
+ def selected_value
266
+ selected_values.first
267
+ end
268
+
269
+ def speak
270
+ @scripter.speak_options_for(self)
271
+ end
272
+
273
+ def tag; "SELECT"; end
274
+ end
275
+
276
+ class Option < InputElement
277
+ def_init :scripter, :select_list, :how, :what
278
+
279
+ def select
280
+ @scripter.highlight(self) do
281
+ select_option
282
+ end
283
+ end
284
+
285
+ def operate(&block)
286
+ @select_list.operate(&block)
287
+ end
288
+
289
+ def exists?
290
+ @scripter.option_exists?(self)
291
+ end
292
+ alias :exist? :exists?
293
+
294
+ def selected?
295
+ @scripter.option_selected?(self)
296
+ end
297
+
298
+ def text
299
+ @scripter.get_text_for(self)
300
+ end
301
+
302
+ def tag; "OPTION"; end
303
+ end
304
+
305
+ class Table
306
+ def_init :scripter, :how, :what
307
+ attr_reader :how, :what
308
+
309
+ def each
310
+ # TODO
311
+ end
312
+
313
+ def [](index)
314
+ TableRow.new(@scripter, :index, index, self)
315
+ end
316
+
317
+ def row_count
318
+ # TODO
319
+ end
320
+
321
+ def column_count
322
+ # TODO
323
+ end
324
+
325
+ def tag; "TABLE"; end
326
+ end
327
+
328
+ class TableRow
329
+ def initialize(scripter, how, what, table = nil)
330
+ @scripter = scripter
331
+ @how = how
332
+ @what = what
333
+ @table = table
334
+ end
335
+
336
+ attr_reader :table, :how, :what
337
+
338
+ def each
339
+ # TODO
340
+ end
341
+
342
+ def [](index)
343
+ TableCell.new(@scripter, :index, index, self)
344
+ end
345
+
346
+ def column_count
347
+ # TODO
348
+ end
349
+
350
+ def tag; "TR"; end
351
+ end
352
+
353
+ class TableCell < ContentElement
354
+ def initialize(scripter, how, what, row = nil)
355
+ @scripter = scripter.for_table(self)
356
+ set_slow_speed # TODO: Need to inherit this somehow
357
+
358
+ @how = how
359
+ @what = what
360
+ @row = row
361
+ end
362
+
363
+ attr_reader :how, :what, :row
364
+
365
+ def operate(&block)
366
+ @scripter.operate_by_table_cell(self, &block)
367
+ end
368
+
369
+ def tag; "TD"; end
370
+ end
371
+
372
+ class TextField < InputElement
373
+ def set(value)
374
+ value = value.to_s
375
+ @scripter.focus(self)
376
+ @scripter.highlight(self) do
377
+ clear_text_input
378
+ value.length.times do |i|
379
+ append_text_input(value[i, 1])
380
+ end
381
+ end
382
+ @scripter.blur(self)
383
+ end
384
+
385
+ def getContents
386
+ @scripter.get_value_for(self)
387
+ end
388
+
389
+ def verify_contains(expected)
390
+ actual = getContents
391
+ case expected
392
+ when Regexp
393
+ actual.match(expected) != nil
394
+ else
395
+ expected == actual
396
+ end
397
+ end
398
+ end
399
+
400
+ class Password < TextField
401
+ end
402
+
403
+
404
+ # Elements
405
+
406
+ def button(how, what)
407
+ Button.new(scripter, how, what)
408
+ end
409
+
410
+ def cell(how, what)
411
+ TableCell.new(scripter, how, what)
412
+ end
413
+
414
+ def checkbox(how, what, value = nil)
415
+ Checkbox.new(scripter, how, what, value)
416
+ end
417
+
418
+
419
+ def form(how, what)
420
+ Form.new(scripter, how, what)
421
+ end
422
+
423
+ def frame(name)
424
+ Frame.new(scripter, name)
425
+ end
426
+
427
+ def image(how, what)
428
+ Image.new(scripter, how, what)
429
+ end
430
+
431
+ def link(how, what)
432
+ Link.new(scripter, how, what)
433
+ end
434
+
435
+ def password(how, what)
436
+ Password.new(scripter, how, what)
437
+ end
438
+
439
+ def radio(how, what, value = nil)
440
+ Radio.new(scripter, how, what, value)
441
+ end
442
+
443
+ def row(how, what)
444
+ TableRow.new(scripter, how, what)
445
+ end
446
+
447
+ def select_list(how, what)
448
+ SelectList.new(scripter, how, what)
449
+ end
450
+
451
+ def table(how, what)
452
+ Table.new(scripter, how, what)
453
+ end
454
+
455
+ def text_field(how, what)
456
+ TextField.new(scripter, how, what)
457
+ end
458
+
459
+ def contains_text(what)
460
+ case what
461
+ when Regexp:
462
+ text =~ what
463
+ when String:
464
+ text.index(what)
465
+ else
466
+ raise MissingWayOfFindingObjectException
467
+ end
468
+ end
469
+
470
+ def method_missing(*args)
471
+ BasicContentElement.new(@scripter, args[0], args[1], args[2])
472
+ end
473
+ end
474
+
475
+ class Safari
476
+ include Container
477
+ include PageContainer
478
+
479
+ def self.start(url = nil)
480
+ safari = new
481
+ safari.goto(url) if url
482
+ safari
483
+ end
484
+
485
+ def initialize
486
+ @scripter = AppleScripter.new(JavaScripter.new)
487
+ @scripter.ensure_window_ready
488
+ set_slow_speed
489
+ end
490
+
491
+ # URL of page
492
+ def url
493
+ scripter.url
494
+ end
495
+
496
+ # Hide's Safari
497
+ def hide
498
+ scripter.hide
499
+ end
500
+
501
+ def close
502
+ scripter.close
503
+ end
504
+
505
+ def quit
506
+ scripter.quit
507
+ end
508
+
509
+ def alert
510
+ AlertWindow.new(scripter)
511
+ end
512
+
513
+ def security_warning
514
+ SecurityWarningWindow.new(scripter)
515
+ end
516
+
517
+ def security_warning_at(url)
518
+ SecurityWarningWindow.new(scripter, url)
519
+ end
520
+
521
+ def goto(url)
522
+ scripter.navigate_to(url)
523
+ end
524
+
525
+ # Reloads the page
526
+ def reload
527
+ scripter.reload
528
+ end
529
+ alias :refresh :reload
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