operawatir 0.3-jruby → 0.3.2-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/Gemfile +6 -2
  2. data/LICENSE +1 -1
  3. data/Rakefile +7 -8
  4. data/VERSION +1 -1
  5. data/bin/desktopwatir +3 -0
  6. data/bin/operawatir +2 -2
  7. data/lib/operadriver/webdriver-opera.jar +0 -0
  8. data/lib/operawatir.rb +14 -8
  9. data/lib/operawatir/browser.rb +49 -38
  10. data/lib/operawatir/compat/collection.rb +6 -0
  11. data/lib/operawatir/compat/element.rb +5 -2
  12. data/lib/operawatir/compat/element_finders.rb +19 -0
  13. data/lib/operawatir/desktop-waiter.rb +144 -0
  14. data/lib/operawatir/desktop_browser.rb +506 -0
  15. data/lib/operawatir/desktop_common.rb +111 -0
  16. data/lib/operawatir/desktop_container.rb +252 -0
  17. data/lib/operawatir/desktop_enums.rb +42 -0
  18. data/lib/operawatir/desktop_exceptions.rb +16 -0
  19. data/lib/operawatir/element.rb +6 -6
  20. data/lib/operawatir/exceptions.rb +3 -0
  21. data/lib/operawatir/keys.rb +116 -0
  22. data/lib/operawatir/platform.rb +59 -0
  23. data/lib/operawatir/quickwidgets.rb +3 -0
  24. data/lib/operawatir/quickwidgets/quick_addressfield.rb +23 -0
  25. data/lib/operawatir/quickwidgets/quick_button.rb +151 -0
  26. data/lib/operawatir/quickwidgets/quick_checkbox.rb +58 -0
  27. data/lib/operawatir/quickwidgets/quick_dialogtab.rb +23 -0
  28. data/lib/operawatir/quickwidgets/quick_dropdown.rb +27 -0
  29. data/lib/operawatir/quickwidgets/quick_editfield.rb +115 -0
  30. data/lib/operawatir/quickwidgets/quick_label.rb +12 -0
  31. data/lib/operawatir/quickwidgets/quick_radiobutton.rb +11 -0
  32. data/lib/operawatir/quickwidgets/quick_searchfield.rb +25 -0
  33. data/lib/operawatir/quickwidgets/quick_tab.rb +66 -0
  34. data/lib/operawatir/quickwidgets/quick_thumbnail.rb +26 -0
  35. data/lib/operawatir/quickwidgets/quick_toolbar.rb +11 -0
  36. data/lib/operawatir/quickwidgets/quick_treeitem.rb +157 -0
  37. data/lib/operawatir/quickwidgets/quick_treeview.rb +27 -0
  38. data/lib/operawatir/quickwidgets/quick_widget.rb +369 -0
  39. data/lib/operawatir/quickwidgets/quick_window.rb +150 -0
  40. data/lib/operawatir/selector.rb +1 -1
  41. data/lib/operawatir/version.rb +0 -1
  42. data/lib/operawatir/window.rb +9 -0
  43. data/operawatir.gemspec +382 -0
  44. data/spec/new_watirspec/browser_spec.rb +279 -0
  45. data/spec/new_watirspec/clipboard_spec.rb +79 -0
  46. data/spec/new_watirspec/collection_spec.rb +387 -0
  47. data/spec/new_watirspec/element_spec.rb +456 -0
  48. data/spec/new_watirspec/guards.rb +39 -0
  49. data/spec/new_watirspec/keys_spec.rb +206 -0
  50. data/spec/new_watirspec/server.rb +91 -0
  51. data/spec/new_watirspec/watirspec_helper.rb +62 -0
  52. data/spec/new_watirspec/window_spec.rb +370 -0
  53. data/utils/launchers/launcher-mac +0 -0
  54. metadata +191 -28
  55. data/.gitmodules +0 -3
@@ -0,0 +1,39 @@
1
+ module WatirSpec
2
+ class Guard
3
+
4
+ attr_accessor :type, :browsers, :data
5
+
6
+ def initialize(type, browsers, data={})
7
+ self.type, self.browsers, self.data = type, browsers, data
8
+ WatirSpec.guards << self
9
+ end
10
+
11
+ def guarded?(browser)
12
+ WatirSpec.guarded? || browsers.include?(browser.name)
13
+ end
14
+
15
+ module Helpers
16
+ def deviates_on(*browsers)
17
+ guard = WatirSpec::Guard.new :deviation, browsers, :file => caller.first
18
+ yield unless guard.guarded?(OperaWatir::Helper.browser)
19
+ end
20
+
21
+ def not_compliant_on(*browsers)
22
+ guard = WatirSpec::Guard.new :non_compliance, browsers, :file => caller.first
23
+ yield unless guard.guarded?(OperaWatir::Helper.browser)
24
+ end
25
+
26
+ def compliant_on(*browsers)
27
+ guard = WatirSpec::Guard.new :compliance, browsers, :file => caller.first
28
+ yield unless guard.guarded?(OperaWatir::Helper.browser)
29
+ end
30
+
31
+ def bug(url, *browsers)
32
+ guard = WatirSpec::Guard.new :bug, browsers, :file => caller.first, :url => url
33
+ yield unless guard.guarded?(OperaWatir::Helper.browser)
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+
@@ -0,0 +1,206 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../watirspec_helper', __FILE__)
3
+
4
+ # keyboard input
5
+ # ---------------
6
+ describe '#keys' do
7
+
8
+ after :each do
9
+ browser.keys.release
10
+ end
11
+
12
+ describe '#send' do
13
+ before :each do
14
+ browser.url = fixture('two_input_fields.html')
15
+ @one = window.find_by_name('one')
16
+ @two = window.find_by_name('two')
17
+ @one.click!
18
+ end
19
+
20
+ it 'types a single character' do
21
+ browser.keys.send 'A'
22
+ @one.value.should == 'A'
23
+ end
24
+
25
+ it 'types a mixed-case string' do
26
+ browser.keys.send 'ABC abc'
27
+ @one.value.should == 'ABC abc'
28
+ end
29
+
30
+ it 'types a string containing multi-byte characters' do
31
+ browser.keys.send 'ルビー 水'
32
+ @one.value.should == 'ルビー 水'
33
+ end
34
+
35
+ it 'types many single characters in sequence' do
36
+ browser.keys.send 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
37
+ 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
38
+ 'W', 'X', 'Y', 'Z'
39
+ @one.value.should == 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
40
+ end
41
+
42
+ it 'moves the caret using arrow keys' do
43
+ browser.keys.send 'AC', :left, 'B'
44
+ @one.value.should == 'ABC'
45
+ end
46
+
47
+ it 'switches to a different input element with tab' do
48
+ browser.keys.send 'AB', :tab, 'C'
49
+ @one.value.should == 'AB'
50
+ @two.value.should == 'C'
51
+ end
52
+
53
+ it 'uses modifier keys' do
54
+ browser.keys.send [:shift, 'a'], 'bc'
55
+ @one.value.should == 'Abc'
56
+ end
57
+
58
+ it 'uses multiple modifier keys to manipulate selection' do
59
+ browser.keys.send 'ABC 123'
60
+
61
+ # Selection using keys works differently on OS X
62
+ if Config::CONFIG['host_os'] =~ /darwin|mac os/
63
+ browser.keys.send [:shift, :alt, :left], :backspace
64
+ else
65
+ browser.keys.send [:shift, :control, :left], :backspace
66
+ end
67
+
68
+ @one.value.should == 'ABC '
69
+ end
70
+
71
+ it 'presses an invalid key' do
72
+ p browser.driver.key('hoobaflooba')
73
+ browser.keys.send(:hoobaflooba).should raise_error InvalidKeyException
74
+ end
75
+ end
76
+
77
+ describe '#down' do
78
+ it 'types a mixed-case string by holding shift' do
79
+ browser.url = fixture('two_input_fields.html')
80
+ window.find_by_name('one').click!
81
+ browser.keys.send 'a'
82
+ browser.keys.down :shift
83
+ browser.keys.send 'b'
84
+ window.find_by_name('one').value.should == 'aB'
85
+ browser.keys.up :shift
86
+ end
87
+
88
+ it 'holds down a non-modifier key for one second' do
89
+ browser.url = fixture('two_input_fields.html')
90
+ window.find_by_name('one').click!
91
+ browser.keys.down 'a'
92
+ sleep 1
93
+ browser.keys.up 'a'
94
+ window.find_by_name('one').value.should include 'aa' # Two or more characters are expected.
95
+ end
96
+
97
+ it 'triggers onkeydown' do
98
+ browser.url = fixture('keys.html')
99
+ browser.keys.down :shift
100
+ window.find_by_id('log').text.should include 'down, 16'
101
+ browser.keys.up :shift
102
+ end
103
+
104
+ it 'does not trigger onkeyup' do
105
+ browser.url = fixture('keys.html')
106
+ browser.keys.down :shift
107
+ window.find_by_id('log').text.should_not include 'up, 16'
108
+ browser.keys.up :shift
109
+ end
110
+
111
+ it 'presses two buttons at the same time' do
112
+ browser.url = fixture('keys.html')
113
+ browser.keys.down :shift, :control
114
+ window.find_by_id('log').text.should include 'down, 16'
115
+ window.find_by_id('log').text.should include 'down, 17'
116
+ browser.keys.up :shift
117
+ browser.keys.up :control
118
+ end
119
+
120
+ it 'presses an invalid key' do
121
+ browser.keys.down(:hoobaflooba).should raise_error InvalidKeyException
122
+ end
123
+
124
+ it 'passes an array instead of a string' do
125
+ browser.keys.down([:shift, :control]).should raise_error NativeException
126
+ end
127
+ end
128
+
129
+ describe '#up' do
130
+ it 'types a mixed-case string by holding shift' do
131
+ browser.url = fixture('two_input_fields.html')
132
+ window.find_by_name('one').click!
133
+ browser.keys.down :shift
134
+ browser.keys.send 'a'
135
+ browser.keys.send 'b' # Testing that we do not release prematurely
136
+ browser.keys.up :shift
137
+ browser.keys.send 'c'
138
+ window.find_by_name('one').value.should == 'ABc'
139
+ end
140
+
141
+ it 'holds down a non-modifier key for one second (but no longer)' do
142
+ browser.url = fixture('two_input_fields.html')
143
+ window.find_by_name('one').click!
144
+ browser.keys.down 'a'
145
+ sleep 1
146
+ browser.keys.up 'a'
147
+ result_string = window.find_by_name('one').value
148
+ sleep 1
149
+ window.find_by_name('one').value.should == result_string
150
+ result_string = nil
151
+ end
152
+
153
+ it 'triggers onkeyup' do
154
+ browser.url = fixture('keys.html')
155
+ browser.keys.down :shift
156
+ browser.keys.up :shift
157
+ window.find_by_id('log').text.should include 'up, 16'
158
+ end
159
+
160
+ it 'presses two buttons, but releases only one' do
161
+ browser.url = fixture('keys.html')
162
+ browser.keys.down :shift, :control
163
+ browser.keys.up :shift
164
+ window.find_by_id('log').text.should include 'up, 16'
165
+ window.find_by_id('log').text.should_not include 'up, 17'
166
+ browser.keys.up :control
167
+ end
168
+
169
+ it 'releases two buttons' do
170
+ browser.url = fixture('keys.html')
171
+ browser.keys.down :shift, :control
172
+ browser.keys.up :shift, :control
173
+ window.find_by_id('log').text.should include 'up, 16'
174
+ window.find_by_id('log').text.should include 'up, 17'
175
+ end
176
+
177
+ it 'presses an invalid key' do
178
+ browser.keys.down(:hoobaflooba).should raise_error InvalidKeyException
179
+ end
180
+
181
+ it 'passes an array instead of a string' do
182
+ browser.keys.up([:shift, :control]).should raise_error NativeException
183
+ end
184
+ end
185
+
186
+ describe '#release' do
187
+ it 'releases one button' do
188
+ browser.url = fixture('two_input_fields.html')
189
+ window.find_by_name('one').click!
190
+ browser.keys.down :shift
191
+ browser.keys.send 'a'
192
+ browser.keys.release
193
+ browser.keys.send 'b'
194
+ window.find_by_name('one').value.should == 'Ab'
195
+ end
196
+
197
+ it 'releases two buttons' do
198
+ browser.url = fixture('keys.html')
199
+ browser.keys.down :shift, :control
200
+ browser.keys.release
201
+ window.find_by_id('log').text.should include 'up, 16'
202
+ window.find_by_id('log').text.should include 'up, 17'
203
+ end
204
+ end
205
+
206
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+ require 'sinatra/base'
3
+
4
+ class WatirSpec::Server < ::Sinatra::Base
5
+
6
+ set :app_file, __FILE__
7
+ set :root, File.dirname(__FILE__)
8
+ set :public, lambda { File.join(root, 'fixtures')}
9
+ set :static, true
10
+ set :run, false
11
+ set :environment, :production
12
+ set :bind, 'localhost'
13
+ set :port, 2000
14
+ set :server, %w[thin mongrel webrick]
15
+
16
+ get '/' do
17
+ self.class.name
18
+ end
19
+
20
+ get '/big' do
21
+ Class.new do
22
+ def each(&blk)
23
+ yield "<html><head><title>Big Content</title></head><body>"
24
+ string = "hello "*205
25
+ 300.times { yield string }
26
+ yield "</body></html>"
27
+ end
28
+ end.new
29
+ end
30
+
31
+ post '/post_to_me' do
32
+ "You posted the following content:\n#{ env['rack.input'].read }"
33
+ end
34
+
35
+ get '/plain_text' do
36
+ content_type 'text/plain'
37
+ 'This is text/plain'
38
+ end
39
+
40
+ get '/ajax' do
41
+ sleep 10
42
+ "A slooow ajax response"
43
+ end
44
+
45
+ get '/charset_mismatch' do
46
+ content_type 'text/html; charset=UTF-8'
47
+ %{
48
+ <html>
49
+ <head>
50
+ <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
51
+ </head>
52
+ <body>
53
+ <h1>ø</h1>
54
+ </body>
55
+ </html>
56
+ }
57
+ end
58
+
59
+ get '/octet_stream' do
60
+ content_type 'application/octet-stream'
61
+ 'This is application/octet-stream'
62
+ end
63
+
64
+ get '/set_cookie' do
65
+ content_type 'text/plain'
66
+ headers 'Set-Cookie' => "monster=/"
67
+
68
+ "C is for cookie, it's good enough for me"
69
+ end
70
+
71
+ get '/header_echo' do
72
+ content_type 'text/plain'
73
+ env.inspect
74
+ end
75
+
76
+ get '/authentication' do
77
+ auth = Rack::Auth::Basic::Request.new(env)
78
+
79
+ unless auth.provided? && auth.credentials == %w[foo bar]
80
+ headers 'WWW-Authenticate' => %(Basic realm="localhost")
81
+ halt 401, 'Authorization Required'
82
+ end
83
+
84
+ "ok"
85
+ end
86
+
87
+ get '/encodable_<stuff>' do
88
+ 'page with characters in URI that need encoding'
89
+ end
90
+
91
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ $LOAD_PATH.unshift File.dirname(__FILE__)
3
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
+ require 'rspec'
5
+
6
+ require 'guards'
7
+ require 'server'
8
+
9
+ require 'operawatir/helper'
10
+
11
+ OperaWatir.api = 2
12
+
13
+ RSpec.configure do |config|
14
+ config.mock_with :rr
15
+ end
16
+
17
+ module WatirSpec
18
+ extend self
19
+
20
+ attr_accessor :args, :guarded
21
+
22
+ def host
23
+ "http://#{Server.bind}:#{Server.port}"
24
+ end
25
+ alias_method :files, :host
26
+
27
+ def guards
28
+ @guards ||= []
29
+ end
30
+
31
+ def guarded?
32
+ !!@guarded
33
+ end
34
+
35
+ module Helpers
36
+ def browser
37
+ OperaWatir::Helper.browser
38
+ end
39
+
40
+ def window
41
+ browser.active_window
42
+ end
43
+
44
+ def fixture(*paths)
45
+ [WatirSpec.host, *paths].join('/')
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ include OperaWatir::Exceptions
52
+
53
+ include WatirSpec::Guard::Helpers
54
+
55
+ RSpec.configure do |config|
56
+ config.include WatirSpec::Helpers
57
+
58
+ config.before(:suite) do
59
+ Thread.new { WatirSpec::Server.run! }
60
+ end
61
+ end
62
+
@@ -0,0 +1,370 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../watirspec_helper', __FILE__)
3
+
4
+ describe 'Window' do
5
+
6
+ before :each do
7
+ browser.url = fixture('non_control_elements.html')
8
+ end
9
+
10
+ # element access
11
+ # --------------
12
+
13
+ describe '#find_by_id' do
14
+ it 'returns an element with the given ID' do
15
+ elements = window.find_by_id('header')
16
+
17
+ elements.should_not be_empty
18
+ elements.length.should == 1
19
+ elements.first.attr(:id).should == 'header'
20
+ end
21
+
22
+ it 'finds multiple elements with the same id' do
23
+ elements = window.find_by_id('lead')
24
+ elements.length.should == 4
25
+ end
26
+ end
27
+
28
+ describe '#find_by_tag' do
29
+ it 'is not empty if the tag exists' do
30
+ window.find_by_tag(:div).should_not be_empty
31
+ end
32
+
33
+ it 'returns a collection of elements of the given tag' do
34
+ uls = window.find_by_tag(:ul)
35
+ uls.length.should == 2
36
+ uls.find_by_tag(:li).all? do |element|
37
+ element.parent.tag_name.match(/ul/i)
38
+ end
39
+ end
40
+
41
+ # TODO I'm not convinced that we should be able to filter in finders
42
+ it 'contains only elements restricted by the selector' do
43
+ window.find_by_tag(:div, :title => 'Lorem ipsum').all? do |element|
44
+ element.attr(:title) == 'Lorem ipsum' && element.tag_name.match(/div/i)
45
+ end.should be_true
46
+ end
47
+
48
+ it 'empty if the elements do not exist' do
49
+ window.find_by_tag(:hoobaflooba).should be_empty
50
+ end
51
+
52
+ end
53
+
54
+ # css
55
+ # we don't want a complete CSS selector test suite here, so just some common
56
+ # selectors
57
+ describe '#find_by_css' do
58
+ it 'is not empty if an element matches the css selector' do
59
+ window.find_by_css('#outer_container > div').should_not be_empty
60
+ end
61
+
62
+ it 'contains all elements selected by the selector' do
63
+ window.find_by_css('#outer_container > div').all? do |element|
64
+ element.parent.attr(:id).should == 'outer_container'
65
+ end.should be_true
66
+ end
67
+
68
+ it 'is empty if the selector does not match' do
69
+ window.find_by_css('#hoobaflooba').should be_empty
70
+ end
71
+ end
72
+
73
+ # class
74
+ describe '#find_by_class' do
75
+ it 'is not empty if an element matches the class' do
76
+ window.find_by_class('lead').should_not be_empty
77
+ end
78
+
79
+ it 'returns a collection of elements with the given class' do
80
+ window.find_by_class('lead').attrs(:class).should == ['lead','lead','lead','lead']
81
+ end
82
+
83
+ it 'finds elements with multiple classes' do
84
+ window.find_by_class('one').all? do |element|
85
+ element.attr(:class).should match /one/
86
+ end.should be_true
87
+ end
88
+
89
+ it 'is empty if the class does not match' do
90
+ window.find_by_class('hoobaflooba').should be_empty
91
+ end
92
+ end
93
+
94
+ # xpath
95
+ describe '#find_by_xpath' do
96
+ before :all do
97
+ @headers = window.find_by_xpath('//h1')
98
+ end
99
+
100
+ it 'is not empty if elements matches the class' do
101
+ @headers.should_not be_empty
102
+ end
103
+
104
+ it 'contains all elements with the given query' do
105
+ @headers.all? do |element|
106
+ element.tag_name.should match /h1/i
107
+ end
108
+ end
109
+
110
+ it 'is empty if the query does not match' do
111
+ window.find_by_xpath('//hoobaflooba').should be_empty
112
+ end
113
+ end
114
+
115
+ # properties
116
+ # ----------
117
+
118
+ describe '#title' do
119
+ it 'is the title of the window' do
120
+ window.title.should == 'Non-control elements'
121
+ end
122
+
123
+ it 'changes when the title tag changes' do
124
+ window.find_by_tag(:title).first.text = 'changed'
125
+ window.title.should == 'changed'
126
+ end
127
+ end
128
+
129
+ describe '#html' do
130
+ it 'is the source of the page' do
131
+ window.html.should match /<title>Non-control elements<\/title>/i
132
+ end
133
+
134
+ # TODO I'm not sure Watir allows DOM manipulation
135
+ it 'is the original source' do
136
+ # window.find_by_tag(:title).first.text = 'changed'
137
+ window.html.should match /<title>Non-control elements<\/title>/i
138
+ end
139
+ end
140
+
141
+ # page management
142
+ # ---------------
143
+
144
+ describe '#url' do
145
+ it 'is the url of this window' do
146
+ window.url.should == fixture('non_control_elements.html')
147
+ end
148
+ end
149
+
150
+ describe '#url=' do
151
+ it 'navigates to the given url' do
152
+ window.url = fixture('forms_with_input_elements.html')
153
+ window.find_by_tag(:title).first.text.should == 'Forms with input elements'
154
+ end
155
+ end
156
+
157
+ describe '#back' do
158
+ # should it raise an exception if it fails instead?
159
+ it 'is possible to go back' do
160
+ window.url = fixture('forms_with_input_elements.html')
161
+ window.back.should be_true
162
+ end
163
+
164
+ it 'is false if there is no page to go back to' do
165
+ # FIXME: We need to open a new window first
166
+ window.back.should be_false
167
+ end
168
+
169
+ it 'goes back one page in history' do
170
+ window.url = fixture('forms_with_input_elements.html')
171
+ window.back
172
+ window.url.should == fixture('non_control_elements.html')
173
+ end
174
+ end
175
+
176
+ describe '#forward' do
177
+ it 'is possible to go forward' do
178
+ window.url = fixture('forms_with_input_elements.html')
179
+ window.back
180
+ window.forward.should be_true
181
+ end
182
+
183
+ it 'there is no page to go forward to' do
184
+ window.forward.should be_false
185
+ end
186
+
187
+ it 'goes forward one page in history' do
188
+ window.url = fixture('forms_with_input_elements.html')
189
+ window.back
190
+ window.forward
191
+ window.url.should == fixture('forms_with_input_elements.html')
192
+ end
193
+ end
194
+
195
+ describe '#refresh' do
196
+ it 'refreshes the current page' do
197
+ window.url = fixture('forms_with_input_elements.html')
198
+ field = window.find_by_id('new_user_first_name').first
199
+ field.value = 'foobar'
200
+ field.value.should == 'foobar'
201
+
202
+ window.refresh
203
+ field.value.should be_empty
204
+ end
205
+ end
206
+
207
+ # actions
208
+ # -------
209
+
210
+ # click(x,y)
211
+
212
+ describe '#type' do
213
+ it 'types the given characters' do
214
+ browser.url = fixture('forms_with_input_elements.html')
215
+ textbox = window.find_by_id('new_user_first_name').first
216
+ textbox.focus!
217
+ window.type('test')
218
+ textbox.attr(:value).should == 'test'
219
+ end
220
+
221
+ it 'sends keypress events' do
222
+ browser.url = fixture('keys.html')
223
+ window.type('hello')
224
+ window.find_by_id('log').text.should include 'press, 104, h,'
225
+ window.find_by_id('log').text.should include 'down, 69, E,'
226
+ window.find_by_id('log').text.should include 'up, 79, O,'
227
+ end
228
+ end
229
+
230
+ describe '#key' do
231
+ before :each do
232
+ browser.url = fixture('keys.html')
233
+ end
234
+
235
+ it 'presses and releases the given key' do
236
+ # TODO Is this how we should send ctrl/shift/alt?
237
+ window.key('ctrl')
238
+
239
+ window.find_by_id('log').text.should include 'down'
240
+ window.find_by_id('log').text.should include 'ctrl'
241
+ window.find_by_id('log').text.should include 'up'
242
+ end
243
+
244
+ it 'can press the home key' do
245
+ window.key('home')
246
+ window.find_by_id('log').text.should include 'press, 36'
247
+ end
248
+
249
+ it 'can press the tab key' do
250
+ window.key('tab')
251
+ window.find_by_id('log').text.should include 'press, 9'
252
+ end
253
+
254
+ it 'tabs through fields when tab is pressed' do
255
+ window.url = fixture('forms_with_input_elements.html')
256
+ window.key('tab')
257
+ window.find_by_id('new_user_first_name').focused?.should be_true
258
+ end
259
+
260
+ it 'can press the F3 key' do
261
+ window.key('f3')
262
+ window.find_by_id('log').text.should include 'press, 114'
263
+ end
264
+ end
265
+
266
+ describe '#key_down' do
267
+ it 'presses down the given key' do
268
+ browser.url = fixture('keys.html')
269
+ window.key_down('ctrl')
270
+ window.key_down('shift')
271
+ window.find_by_id('log').text.should include 'ctrl,shift'
272
+ # Don't leave them pressed down
273
+ window.key_up('ctrl')
274
+ window.key_up('shift')
275
+ end
276
+ end
277
+
278
+ describe '#key_up' do
279
+ it 'releases the given key' do
280
+ browser.url = fixture('keys.html')
281
+ window.key_down('ctrl')
282
+ window.key_up('ctrl')
283
+ window.find_by_id('log').text.should include 'up, 17'
284
+ end
285
+ end
286
+
287
+ describe '#eval_js' do
288
+ it 'executes Javascript in the page' do
289
+ window.eval_js('document.title = "test"')
290
+ window.title.should == 'test'
291
+ end
292
+
293
+ it 'returns an element when the Javascript does' do
294
+ window.eval_js('document.createElement("div")').tag_name.should match /div/i
295
+ end
296
+
297
+ it 'returns a number when the Javascript does' do
298
+ window.eval_js('Math.abs(-5)').should == 5
299
+ end
300
+
301
+ it 'returns a boolean when the Javascript does' do
302
+ window.eval_js('(function(){return true;})()').should be_true
303
+ end
304
+
305
+ it 'returns an array when the Javascript does' do
306
+ result = window.eval_js('["this", "is", "a", "test"]') # WTR-227
307
+ result.length.should == 4
308
+ result[3].should == 'test'
309
+ end
310
+
311
+ it 'returns a string when the result is not one of these types' do
312
+ window.eval_js('({one:"two"}).toString()').should == '[object Object]'
313
+ end
314
+ end
315
+
316
+ # window management
317
+ # -----------------
318
+
319
+ describe '#maximize' do
320
+ before :each do
321
+ # Make sure we aren't already maximized
322
+ window.restore
323
+ end
324
+
325
+ it 'maximizes the window' do
326
+ body = window.find_by_tag(:body).first
327
+ width = body.width
328
+ window.maximize
329
+ body.width.should be > width
330
+ end
331
+ end
332
+
333
+ describe '#restore' do
334
+ it 'restores (unmaximizes) the window' do
335
+ body = window.find_by_tag(:body).first
336
+ # Make sure we aren't already restored
337
+ window.maximize
338
+ width = body.width
339
+ window.restore
340
+ body.width.should be < width
341
+ end
342
+ end
343
+
344
+ describe '#exists?' do
345
+ it 'is true if the window exists' do
346
+ window.exists?.should be_true
347
+ end
348
+
349
+ it 'is false if the window does not exist' do
350
+ window.close
351
+ window.exists?.should be_false
352
+ end
353
+ end
354
+
355
+ describe '#close' do
356
+ it 'destroys the window' do
357
+ window.close
358
+ window.exists?.should be_false
359
+ window.find_by_tag(:title).should raise_error
360
+ end
361
+ end
362
+
363
+ describe '#new' do
364
+ it 'creates a new window' do
365
+ new_window = browser.url(fixture('non_control_elements.html'))
366
+ new_window.exists?.should be_true
367
+ new_window.url.should == fixture('non_control_elements.html')
368
+ end
369
+ end
370
+ end