safariwatir 0.1.2 → 0.2.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/safariwatir.rb CHANGED
@@ -269,10 +269,6 @@ module Watir
269
269
 
270
270
  attr_reader :how, :what, :row
271
271
 
272
- def operate_by_index(&block)
273
- @scripter.operate_by_table_cell_index(self, &block)
274
- end
275
-
276
272
  def operate(&block)
277
273
  @scripter.operate_by_table_cell(self, &block)
278
274
  end
@@ -294,7 +290,12 @@ module Watir
294
290
 
295
291
  def verify_contains(expected)
296
292
  actual = getContents
297
- expected == actual
293
+ case expected
294
+ when Regexp
295
+ actual.match(expected) != nil
296
+ else
297
+ expected == actual
298
+ end
298
299
  end
299
300
  end
300
301
 
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/core_ext'
2
2
  require File.dirname(__FILE__) + '/../watir/exceptions'
3
+ require 'appscript'
3
4
 
4
5
  module Watir
5
6
  ELEMENT_NOT_FOUND = "__safari_watir_element_unfound__"
@@ -9,20 +10,21 @@ module Watir
9
10
 
10
11
  class JavaScripter
11
12
  def operate(locator, operation)
12
- wrap(%|
13
- #{locator}
13
+ %|#{locator}
14
14
  if (element) {
15
15
  #{operation}
16
16
  } else {
17
17
  return '#{ELEMENT_NOT_FOUND}';
18
- }|)
18
+ }|
19
19
  end
20
-
20
+
21
21
  def wrap(script)
22
+ # Needed because createEvent must be called on a document, and the JavaScripter sub-classes
23
+ # do some transformations to lower-case "document" before we get here at runtime.
22
24
  script.gsub! "DOCUMENT", "document"
23
- %|set response to do JavaScript "#{script}" in document 1|
25
+ script
24
26
  end
25
-
27
+
26
28
  def find_cell(cell)
27
29
  return %|getElementById('#{cell.what}')| if cell.how == :id
28
30
  raise RuntimeError, "Unable to use #{cell.how} to find TableCell" unless cell.row
@@ -80,23 +82,28 @@ if (element) {
80
82
 
81
83
  def initialize(scripter = JavaScripter.new)
82
84
  @js = scripter
85
+ @app = AS.app("Safari")
86
+ @document = @app.documents[1]
83
87
  end
84
88
 
85
89
  def ensure_window_ready
86
- execute(%|
87
- activate
88
- set document_list to every document
89
- if length of document_list is 0 then
90
- make new document
91
- end if|)
90
+ @app.activate
91
+ @app.make(:new => :document) if @app.documents.get.size == 0
92
+ @document = @app.documents[1]
92
93
  end
93
94
 
94
95
  def close
95
- execute(%|quit|)
96
+ @app.quit
96
97
  end
97
98
 
98
99
  def navigate_to(url)
99
- execute_and_wait(%|set URL in document 1 to "#{url}"|)
100
+ page_load do
101
+ @document.URL.set(url)
102
+ end
103
+ end
104
+
105
+ def current_location
106
+ eval_js("window.location.href")
100
107
  end
101
108
 
102
109
  def get_text_for(element = @element)
@@ -104,12 +111,11 @@ end if|)
104
111
  end
105
112
 
106
113
  def operate_by_table_cell(element = @element)
107
- js.wrap(%|
108
- var element = document;
114
+ %|var element = document;
109
115
  if (element == undefined) {
110
116
  return '#{TABLE_CELL_NOT_FOUND}';
111
117
  }
112
- #{yield}|)
118
+ #{yield}|
113
119
  end
114
120
 
115
121
  def get_value_for(element = @element)
@@ -117,7 +123,7 @@ if (element == undefined) {
117
123
  end
118
124
 
119
125
  def document_text
120
- execute(js.wrap(%|document.getElementsByTagName('BODY').item(0).innerText;|))
126
+ execute(%|document.getElementsByTagName('BODY').item(0).innerText;|)
121
127
  end
122
128
 
123
129
  def highlight(element, &block)
@@ -177,22 +183,23 @@ element.setSelectionRange(element.value.length, element.value.length);|
177
183
  end, element)
178
184
  end
179
185
 
180
- # TODO need a better approach for "waiting"
181
186
  def click_element(element = @element)
182
- execute_and_wait(element.operate { %|
187
+ page_load do
188
+ execute(element.operate { %|
183
189
  if (element.click) {
184
190
  element.click();
185
191
  } else {
186
- var event = document.createEvent('MouseEvents');
192
+ var event = DOCUMENT.createEvent('MouseEvents');
187
193
  event.initEvent('click', true, true);
188
194
  element.dispatchEvent(event);
189
195
 
190
196
  if (element.onclick) {
191
- var event = document.createEvent('HTMLEvents');
197
+ var event = DOCUMENT.createEvent('HTMLEvents');
192
198
  event.initEvent('click', true, true);
193
199
  element.onclick(event);
194
200
  }
195
201
  }| })
202
+ end
196
203
  end
197
204
 
198
205
  def click_link(element = @element)
@@ -230,7 +237,9 @@ if (element.onclick) {
230
237
  } else {
231
238
  nextLocation(element);
232
239
  }/
233
- execute_and_wait(js.operate(find_link(element), click))
240
+ page_load do
241
+ execute(js.operate(find_link(element), click))
242
+ end
234
243
  end
235
244
 
236
245
  def operate_on_link(element)
@@ -271,11 +280,9 @@ for (var i = 0; i < document.links.length; i++) {
271
280
  var elements = document.getElementsByTagName('INPUT');
272
281
  var element = undefined;
273
282
  for (var i = 0; i < elements.length; i++) {
274
- if (elements[i].tagName != 'META') {
275
- if (elements[i].value == '#{element.what}') {
276
- element = elements[i];
277
- break;
278
- }
283
+ if (elements[i].value == '#{element.what}') {
284
+ element = elements[i];
285
+ break;
279
286
  }
280
287
  }|, yield)
281
288
  end
@@ -323,7 +330,9 @@ for (var i = 0; i < elements.length; i++) {
323
330
  end
324
331
 
325
332
  def submit_form(element)
326
- execute_and_wait(element.operate { %|element.submit();| })
333
+ page_load do
334
+ execute(element.operate { %|element.submit();| })
335
+ end
327
336
  end
328
337
 
329
338
  def click_alert_ok
@@ -341,10 +350,10 @@ end tell|)
341
350
 
342
351
  def for_frame(element)
343
352
  # verify the frame exists
344
- execute(js.wrap(%|
345
- if (parent.#{element.name} == undefined) {
353
+ execute(
354
+ %|if (parent.#{element.name} == undefined) {
346
355
  return '#{FRAME_NOT_FOUND}';
347
- }|), element)
356
+ }|, element)
348
357
  AppleScripter.new(FrameJavaScripter.new(element))
349
358
  end
350
359
 
@@ -379,18 +388,8 @@ SCRIPT`
379
388
 
380
389
  private
381
390
 
382
- def execute!(script)
383
- `osascript <<SCRIPT
384
- tell application "Safari"
385
- set response to "#{NO_RESPONSE}"
386
- #{script}
387
- response
388
- end tell
389
- SCRIPT`.chomp
390
- end
391
-
392
391
  def execute(script, element = nil)
393
- response = execute! script
392
+ response = eval_js(script)
394
393
  case response
395
394
  when NO_RESPONSE:
396
395
  nil
@@ -406,7 +405,7 @@ SCRIPT`.chomp
406
405
  end
407
406
 
408
407
  def execute_and_ignore(script)
409
- execute! script
408
+ eval_js(script)
410
409
  nil
411
410
  end
412
411
 
@@ -419,19 +418,43 @@ end tell
419
418
  SCRIPT`
420
419
  nil
421
420
  end
421
+
422
+ def page_load
423
+ last_location = current_location
424
+ yield
425
+ sleep 1
426
+ return if last_location == current_location
427
+
428
+ tries = 0
429
+ TIMEOUT.times do |tries|
430
+ if "complete" == eval_js("DOCUMENT.readyState")
431
+ handle_client_redirect
432
+ break
433
+ else
434
+ sleep 1
435
+ end
436
+ end
437
+ raise "Unable to load page withing #{TIMEOUT} seconds" if tries == TIMEOUT-1
438
+ end
422
439
 
423
- def execute_and_wait(script, element = nil)
424
- execute(%|
425
- #{script}
426
- delay 2
427
- repeat with i from 1 to #{TIMEOUT}
428
- #{js.wrap("document.readyState")}
429
- if (response) is "complete" then
430
- exit repeat
431
- else
432
- delay 1
433
- end if
434
- end repeat|, element)
440
+ def handle_client_redirect
441
+ no_redirect_flag = "proceed"
442
+ redirect = eval_js(
443
+ %|var elements = DOCUMENT.getElementsByTagName('META');
444
+ for (var i = 0; i < elements.length; i++) {
445
+ if ("refresh" == elements[i].httpEquiv && elements[i].content != undefined && elements[i].content.indexOf(";") != "-1") {
446
+ return elements[i].content;
447
+ }
448
+ }
449
+ return "#{no_redirect_flag}"|)
450
+ if redirect != no_redirect_flag
451
+ time_til_redirect = redirect.split(";").first.to_i
452
+ sleep time_til_redirect
453
+ end
454
+ end
455
+
456
+ def eval_js(script)
457
+ @app.do_JavaScript(js.wrap(script), :in => @document)
435
458
  end
436
459
  end # class AppleScripter
437
460
  end
@@ -2,16 +2,13 @@ require 'rubygems'
2
2
  require 'safariwatir'
3
3
 
4
4
  # TODO
5
- # Need to give feedback when browser dies
6
5
  # Be more attached to the Safari window. Currently, if a different window is selected, the AppleScript executes against it.
7
6
  # Verify onclick is working for buttons and links
8
7
  # TextFields should not respond to button method, etc.
9
8
 
10
9
  # Unsupported Elements: Test that P/Div/Span/TD handle link, button, etc., Javascript confirm [OK/CANCEL], Javascript prompt, Javascript popup windows
11
- # Use dynamic properties for Javascript optimization? Or use global lookup table?
12
- # Will I need to push more functionality into AppleScript to speed things up?
13
- # Angrez is looking into the Ruby/AppleScript binding
14
- # Watir Rails Plugin needed -> Watir test generator, fixtures and AR in-test, Browser Factory
10
+
11
+ # Need to find a better way to distinguish between a submit button and a checkbox, re: page_load
15
12
 
16
13
  # SAFARI ISSUES
17
14
  # Labels are not clickable
@@ -28,8 +25,8 @@ def safari.google_to_prag
28
25
  link(:url, "http://www.pragmaticprogrammer.com/titles/ruby/code/index.html").click
29
26
  link(:text, "Catalog").click
30
27
  # site was down
31
- # link(:text, "All Books").click
32
- goto("http://pragmaticprogrammer.com/bookshelf/") # workaround
28
+ link(:text, "All Books").click
29
+ # goto("http://pragmaticprogrammer.com/bookshelf/") # workaround
33
30
  link(:text, /Agile Retrospectives/).click
34
31
  puts "FAILURE prag" unless contains_text("Dave Hoover")
35
32
  end
@@ -44,9 +41,9 @@ end
44
41
 
45
42
  def safari.amazon
46
43
  goto("http://amazon.com")
47
- select_list(:name, "url").select("Toys")
48
- select_list(:name, "url").select_value("index=software")
49
- text_field(:name, "keywords").set("Orion")
44
+ select_list(:name, "url").select("VHS")
45
+ select_list(:name, "url").select_value("search-alias=software")
46
+ text_field(:name, "field-keywords").set("Orion")
50
47
  image(:name, "Go").click
51
48
  puts "FAILURE amazon" unless contains_text("Master of Orion")
52
49
  end
@@ -75,7 +72,7 @@ def safari.colbert
75
72
  goto("http://www.colbertnation.com/cn/contact.php")
76
73
  text_field(:name, "formmessage").set("Beware the Bear")
77
74
  button(:value, "Send Email").click
78
- puts "FAILURE colbert" unless text_field(:name, "formmessage").verify_contains("Enter message")
75
+ puts "FAILURE colbert" unless text_field(:name, "formmessage").verify_contains(/Enter message/)
79
76
  end
80
77
 
81
78
  def safari.redsquirrel
@@ -122,14 +119,16 @@ def safari.tables
122
119
  puts "FAILURE dreamweaver" unless table(:id, "titletable")[1][1].text =~ /CSS/
123
120
  end
124
121
 
125
- safari.google_to_prag
126
- safari.ala
127
- safari.amazon
128
- safari.google_advanced
129
- safari.reddit
130
- safari.colbert
131
- safari.redsquirrel
132
- safari.weinberg
133
- safari.tables
134
-
135
- safari.close
122
+ begin
123
+ safari.google_to_prag
124
+ safari.ala
125
+ safari.amazon
126
+ safari.google_advanced
127
+ safari.reddit
128
+ safari.colbert
129
+ safari.redsquirrel
130
+ safari.weinberg
131
+ safari.tables
132
+ ensure
133
+ safari.close
134
+ end
metadata CHANGED
@@ -3,15 +3,15 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: safariwatir
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.2
7
- date: 2006-10-12 00:00:00 -05:00
6
+ version: 0.2.0
7
+ date: 2006-11-22 00:00:00 -06:00
8
8
  summary: Automated testing tool for web applications.
9
9
  require_paths:
10
10
  - .
11
11
  email: dave.hoover@gmail.com
12
12
  homepage: http://safariwatir.rubyforge.org/
13
13
  rubyforge_project: safariwatir
14
- description: WATIR stands for "Web Application Testing in Ruby". See WATIR project for more information. This is simply a Safari-version of the original IE-only WATIR.
14
+ description: 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.
15
15
  autorequire: safariwatir
16
16
  default_executable:
17
17
  bindir: bin
@@ -46,5 +46,13 @@ extensions: []
46
46
  requirements:
47
47
  - Mac OS X running Safari
48
48
  - Some features require you to turn on "Enable access for assistive devices" in System Preferences > Universal Access
49
- dependencies: []
50
-
49
+ dependencies:
50
+ - !ruby/object:Gem::Dependency
51
+ name: rb-appscript
52
+ version_requirement:
53
+ version_requirements: !ruby/object:Gem::Version::Requirement
54
+ requirements:
55
+ - - ">"
56
+ - !ruby/object:Gem::Version
57
+ version: 0.0.0
58
+ version: