safariwatir 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: