lebowski 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +3 -0
- data/License.txt +20 -0
- data/Manifest.txt +84 -0
- data/README.md +146 -0
- data/Rakefile +42 -0
- data/bin/lebowski +26 -0
- data/bin/lebowski-spec +29 -0
- data/bin/lebowski-start-server +24 -0
- data/lib/lebowski.rb +15 -0
- data/lib/lebowski/core.rb +35 -0
- data/lib/lebowski/foundation.rb +52 -0
- data/lib/lebowski/foundation/application.rb +315 -0
- data/lib/lebowski/foundation/core.rb +61 -0
- data/lib/lebowski/foundation/core_query.rb +231 -0
- data/lib/lebowski/foundation/dom_element.rb +114 -0
- data/lib/lebowski/foundation/errors/argument_invalid_type.rb +31 -0
- data/lib/lebowski/foundation/errors/unexpected_type.rb +30 -0
- data/lib/lebowski/foundation/mixins/collection_item_view_support.rb +87 -0
- data/lib/lebowski/foundation/mixins/delegate_support.rb +22 -0
- data/lib/lebowski/foundation/mixins/inline_text_field_support.rb +29 -0
- data/lib/lebowski/foundation/mixins/key_check.rb +35 -0
- data/lib/lebowski/foundation/mixins/list_item_view_support.rb +36 -0
- data/lib/lebowski/foundation/mixins/positioned_element.rb +20 -0
- data/lib/lebowski/foundation/mixins/stall_support.rb +79 -0
- data/lib/lebowski/foundation/mixins/user_actions.rb +302 -0
- data/lib/lebowski/foundation/mixins/wait_actions.rb +44 -0
- data/lib/lebowski/foundation/object_array.rb +305 -0
- data/lib/lebowski/foundation/panes/alert.rb +117 -0
- data/lib/lebowski/foundation/panes/main.rb +20 -0
- data/lib/lebowski/foundation/panes/menu.rb +100 -0
- data/lib/lebowski/foundation/panes/modal.rb +21 -0
- data/lib/lebowski/foundation/panes/palette.rb +21 -0
- data/lib/lebowski/foundation/panes/pane.rb +24 -0
- data/lib/lebowski/foundation/panes/panel.rb +25 -0
- data/lib/lebowski/foundation/panes/picker.rb +43 -0
- data/lib/lebowski/foundation/panes/sheet.rb +21 -0
- data/lib/lebowski/foundation/proxy_factory.rb +87 -0
- data/lib/lebowski/foundation/proxy_object.rb +670 -0
- data/lib/lebowski/foundation/sc_object.rb +38 -0
- data/lib/lebowski/foundation/views/button.rb +20 -0
- data/lib/lebowski/foundation/views/checkbox.rb +63 -0
- data/lib/lebowski/foundation/views/collection.rb +304 -0
- data/lib/lebowski/foundation/views/container.rb +32 -0
- data/lib/lebowski/foundation/views/disclosure.rb +59 -0
- data/lib/lebowski/foundation/views/grid.rb +21 -0
- data/lib/lebowski/foundation/views/label.rb +30 -0
- data/lib/lebowski/foundation/views/list.rb +67 -0
- data/lib/lebowski/foundation/views/list_item.rb +280 -0
- data/lib/lebowski/foundation/views/menu_item.rb +27 -0
- data/lib/lebowski/foundation/views/radio.rb +32 -0
- data/lib/lebowski/foundation/views/segmented.rb +97 -0
- data/lib/lebowski/foundation/views/select_field.rb +139 -0
- data/lib/lebowski/foundation/views/support/simple_item_array.rb +249 -0
- data/lib/lebowski/foundation/views/text_field.rb +108 -0
- data/lib/lebowski/foundation/views/view.rb +108 -0
- data/lib/lebowski/runtime.rb +7 -0
- data/lib/lebowski/runtime/errors/remote_control_command_execution_error.rb +9 -0
- data/lib/lebowski/runtime/errors/remote_control_command_timeout_error.rb +9 -0
- data/lib/lebowski/runtime/errors/remote_control_error.rb +9 -0
- data/lib/lebowski/runtime/errors/selenium_server_error.rb +9 -0
- data/lib/lebowski/runtime/object_encoder.rb +123 -0
- data/lib/lebowski/runtime/sprout_core_driver.rb +14 -0
- data/lib/lebowski/runtime/sprout_core_extensions.rb +600 -0
- data/lib/lebowski/scui.rb +18 -0
- data/lib/lebowski/scui/mixins/node_item_view_support.rb +136 -0
- data/lib/lebowski/scui/mixins/terminal_view_support.rb +25 -0
- data/lib/lebowski/scui/views/combo_box.rb +119 -0
- data/lib/lebowski/scui/views/date_picker.rb +148 -0
- data/lib/lebowski/scui/views/linkit.rb +36 -0
- data/lib/lebowski/spec.rb +17 -0
- data/lib/lebowski/spec/core.rb +21 -0
- data/lib/lebowski/spec/matchers/be.rb +63 -0
- data/lib/lebowski/spec/matchers/has.rb +40 -0
- data/lib/lebowski/spec/matchers/match_supporters/has_object_function.rb +67 -0
- data/lib/lebowski/spec/matchers/match_supporters/has_predicate_with_no_prefix.rb +50 -0
- data/lib/lebowski/spec/matchers/match_supporters/has_predicate_with_prefix_has.rb +50 -0
- data/lib/lebowski/spec/matchers/match_supporters/match_supporter.rb +29 -0
- data/lib/lebowski/spec/matchers/method_missing.rb +24 -0
- data/lib/lebowski/spec/operators/operator.rb +20 -0
- data/lib/lebowski/spec/operators/that.rb +116 -0
- data/lib/lebowski/spec/util.rb +26 -0
- data/lib/lebowski/version.rb +17 -0
- data/resources/selenium-server.jar +0 -0
- data/resources/user-extensions.js +1421 -0
- metadata +198 -0
@@ -0,0 +1,315 @@
|
|
1
|
+
# ==========================================================================
|
2
|
+
# Project: Lebowski Framework - The SproutCore Test Automation Framework
|
3
|
+
# License: Licensed under MIT license (see License.txt)
|
4
|
+
# ==========================================================================
|
5
|
+
|
6
|
+
module Lebowski
|
7
|
+
module Foundation
|
8
|
+
|
9
|
+
#
|
10
|
+
# This class represents a SproutCore-based application. In order to interact with the
|
11
|
+
# actual application you must create an instance of this class and start it. Once
|
12
|
+
# started, you are then free to access any object or view that has been created by
|
13
|
+
# the application within the web browser.
|
14
|
+
#
|
15
|
+
class Application < Lebowski::Foundation::SCObject
|
16
|
+
include Lebowski
|
17
|
+
include Lebowski::Foundation
|
18
|
+
include Lebowski::Foundation::Panes
|
19
|
+
include Lebowski::Foundation::Mixins::KeyCheck
|
20
|
+
|
21
|
+
SAFARI = '*safari'
|
22
|
+
FIREFOX = '*firefox'
|
23
|
+
CHROME = '*chrome'
|
24
|
+
|
25
|
+
DEFAULT_BROWSER = FIREFOX
|
26
|
+
DEFAULT_SELENIUM_SERVER_HOST = 'localhost'
|
27
|
+
DEFAULT_SELENIUM_SERVER_PORT = 4444
|
28
|
+
DEFAULT_APP_SERVER_HOST = 'localhost'
|
29
|
+
DEFAULT_APP_SERVER_PORT = 4020
|
30
|
+
DEFAULT_TIMEOUT_IN_SECONDS = 240
|
31
|
+
|
32
|
+
attr_reader :app_name,
|
33
|
+
:app_root_path,
|
34
|
+
:host,
|
35
|
+
:port,
|
36
|
+
:base_url,
|
37
|
+
:session_id,
|
38
|
+
:browser,
|
39
|
+
:app_is_loaded_flag
|
40
|
+
|
41
|
+
#
|
42
|
+
# Creates an Application instance that will allow you to interact with a
|
43
|
+
# SproutCore-based application.
|
44
|
+
#
|
45
|
+
# Initialization requires a hash input containing parameters to set up
|
46
|
+
# the application instance. At minimum, the following are required
|
47
|
+
#
|
48
|
+
# app_root_path => The root URL path to the SproutCore-based application (e.g. /my_app)
|
49
|
+
# app_name => The name of the application's root object (e.g. MyApp)
|
50
|
+
#
|
51
|
+
# In addition to the two required params, the following optional params can
|
52
|
+
# also be supplied:
|
53
|
+
#
|
54
|
+
# selenium_server_host => The name of the host the selenium server is running on (default is localhost)
|
55
|
+
# selenium_server_port => The port the selenium server is listening on (default is 4444)
|
56
|
+
# app_server_host => The name of the server hosting the web application (defalt is localhost)
|
57
|
+
# app_server_port => The port on the server to access the web application (default is 4020)
|
58
|
+
# browser => The web browser to load the web application in to (default is SAFARI)
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
#
|
62
|
+
# Lebowski::Foundation::Application.new \
|
63
|
+
# :app_root_path => "/hello_world",
|
64
|
+
# :app_name => "HelloWorldApp"
|
65
|
+
#
|
66
|
+
def initialize(params)
|
67
|
+
super()
|
68
|
+
|
69
|
+
if params.nil?
|
70
|
+
raise ArgumentError.new "must supply parameters to create application instance"
|
71
|
+
end
|
72
|
+
|
73
|
+
if not params.kind_of?(Hash)
|
74
|
+
raise ArgumentError.new "must supply a hash containing parameters"
|
75
|
+
end
|
76
|
+
|
77
|
+
@host = get_selenium_server_host(params)
|
78
|
+
@port = get_selenium_server_port(params)
|
79
|
+
@browser = get_browser(params)
|
80
|
+
|
81
|
+
@app_root_path = get_app_root_path(params)
|
82
|
+
raise ArgumentError.new "Application root path is required - :app_root_path" if @app_root_path.nil?
|
83
|
+
|
84
|
+
@app_name = get_app_name(params)
|
85
|
+
raise ArgumentError.new "Application name is required - :app_name" if @app_name.nil?
|
86
|
+
|
87
|
+
@rel_path = @app_name
|
88
|
+
@app_is_loaded_flag = get_app_is_loaded_flag(params)
|
89
|
+
@timeout_in_seconds = get_timeout_in_second(params)
|
90
|
+
@base_url = get_application_base_url(params)
|
91
|
+
@session_id = get_session_id(params)
|
92
|
+
|
93
|
+
@driver = Lebowski::Runtime::SproutCoreDriver.new \
|
94
|
+
:host => @host,
|
95
|
+
:port => @port,
|
96
|
+
:browser => @browser,
|
97
|
+
:url => @base_url,
|
98
|
+
:timeout_in_second => @timeout_in_seconds
|
99
|
+
|
100
|
+
@started = false
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Responsible for starting the application. The application will create
|
105
|
+
# an internal driver that is used to actually communicate with the
|
106
|
+
# selenium server.
|
107
|
+
#
|
108
|
+
# You can optionally supply a block used to wait until some condition
|
109
|
+
# has been satisfied before going on and running the rest of your script.
|
110
|
+
# Example:
|
111
|
+
#
|
112
|
+
# application.start do |it|
|
113
|
+
# it['appIsLoaded'] == true
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# If the condition does not become true before timing out then an exception
|
117
|
+
# will be thrown. You can adjust the timeout like so,
|
118
|
+
#
|
119
|
+
# application.start(20) do |it|
|
120
|
+
# it['appIsLoaded'] == true
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
def start(timeout=nil, &block)
|
124
|
+
return if started?
|
125
|
+
|
126
|
+
begin
|
127
|
+
if @session_id.nil?
|
128
|
+
@driver.start
|
129
|
+
else
|
130
|
+
@driver.session_id = @session_id
|
131
|
+
end
|
132
|
+
|
133
|
+
@driver.set_application_name @app_name
|
134
|
+
@driver.open_sc_application @app_root_path, @timeout_in_seconds
|
135
|
+
@started = true
|
136
|
+
rescue Exception => ex
|
137
|
+
err_message = "Error connecting to selenium server: #{ex.message}\n"
|
138
|
+
err_message << "Confirm that selenium server is running on #{@selenium_server_host}:#{@selenium_server_port}"
|
139
|
+
raise Runtime::SeleniumServerError.new err_message
|
140
|
+
end
|
141
|
+
|
142
|
+
if block_given?
|
143
|
+
begin
|
144
|
+
wait_until(timeout, &block)
|
145
|
+
rescue TimeoutError => toe
|
146
|
+
err_message = "Unable to start application. Wait condition was not met before timeout. #{toe.message}"
|
147
|
+
raise TimeoutError.new err_message
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
def end()
|
154
|
+
return if (not started?)
|
155
|
+
|
156
|
+
begin
|
157
|
+
@driver.stop
|
158
|
+
@started = false
|
159
|
+
rescue Exception => ex
|
160
|
+
err_message = "Error disconnecting from selenium server: #{ex.message}\n"
|
161
|
+
err_message << "Confirm that selenium server is running on #{@selenium_server_host}:#{@selenium_server_port}"
|
162
|
+
raise Runtime::SeleniumServerError.new err_message
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def started?()
|
167
|
+
return @started
|
168
|
+
end
|
169
|
+
|
170
|
+
def window()
|
171
|
+
@window = Window.new(@driver) if @window.nil?
|
172
|
+
return @window
|
173
|
+
end
|
174
|
+
|
175
|
+
def abs_path()
|
176
|
+
return nil
|
177
|
+
end
|
178
|
+
|
179
|
+
def root_object(name, expected_type=nil)
|
180
|
+
return self['$' + name, expected_type]
|
181
|
+
end
|
182
|
+
|
183
|
+
alias_method :framework, :root_object
|
184
|
+
|
185
|
+
def main_pane(expected_type=nil)
|
186
|
+
return self['$SC.RootResponder.responder.mainPane', expected_type]
|
187
|
+
end
|
188
|
+
|
189
|
+
def key_pane(expected_type=nil)
|
190
|
+
return self['$SC.RootResponder.responder.keyPane', expected_type]
|
191
|
+
end
|
192
|
+
|
193
|
+
def responding_panes()
|
194
|
+
if @responding_panes.nil?
|
195
|
+
@responding_panes = ObjectArray.new self, '$SC.RootResponder.responder.panes'
|
196
|
+
end
|
197
|
+
return @responding_panes
|
198
|
+
end
|
199
|
+
|
200
|
+
def define_root_object(key, name, expected_type=nil)
|
201
|
+
return define(key, '$' + name, expected_type)
|
202
|
+
end
|
203
|
+
|
204
|
+
alias_method :define_framework, :define_root_object
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
def get_selenium_client(params)
|
209
|
+
return params[:driver]
|
210
|
+
end
|
211
|
+
|
212
|
+
def get_selenium_server_host(params)
|
213
|
+
client = get_selenium_client(params)
|
214
|
+
return client.host if (not client.nil?)
|
215
|
+
return DEFAULT_SELENIUM_SERVER_HOST if params[:selenium_server_host].nil?
|
216
|
+
return params[:selenium_server_host]
|
217
|
+
end
|
218
|
+
|
219
|
+
def get_selenium_server_port(params)
|
220
|
+
client = get_selenium_client(params)
|
221
|
+
return client.port if (not client.nil?)
|
222
|
+
return DEFAULT_SELENIUM_SERVER_PORT if params[:selenium_server_port].nil?
|
223
|
+
return params[:selenium_server_port].to_i
|
224
|
+
end
|
225
|
+
|
226
|
+
def get_app_server_host(params)
|
227
|
+
return DEFAULT_APP_SERVER_HOST if params[:app_server_host].nil?
|
228
|
+
return params[:app_server_host]
|
229
|
+
end
|
230
|
+
|
231
|
+
def get_app_server_port(params)
|
232
|
+
return DEFAULT_APP_SERVER_PORT if params[:app_server_port].nil?
|
233
|
+
return params[:app_server_port].to_i
|
234
|
+
end
|
235
|
+
|
236
|
+
def get_application_base_url(params)
|
237
|
+
client = get_selenium_client(params)
|
238
|
+
return client.browser_url if (not client.nil?)
|
239
|
+
return "http://#{get_app_server_host(params)}:#{get_app_server_port(params)}"
|
240
|
+
end
|
241
|
+
|
242
|
+
def get_session_id(params)
|
243
|
+
client = get_selenium_client(params)
|
244
|
+
return client.session_id if (not client.nil?)
|
245
|
+
return nil
|
246
|
+
end
|
247
|
+
|
248
|
+
def get_browser(params)
|
249
|
+
client = get_selenium_client(params)
|
250
|
+
return client.browser_string if (not client.nil?)
|
251
|
+
|
252
|
+
browser = params[:browser]
|
253
|
+
case (browser)
|
254
|
+
when :firefox
|
255
|
+
return FIREFOX
|
256
|
+
when :safari
|
257
|
+
return SAFARI
|
258
|
+
else
|
259
|
+
return DEFAULT_BROWSER
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def get_app_root_path(params)
|
264
|
+
return params[:app_root_path]
|
265
|
+
end
|
266
|
+
|
267
|
+
def get_app_name(params)
|
268
|
+
return params[:app_name]
|
269
|
+
end
|
270
|
+
|
271
|
+
def get_app_is_loaded_flag(params)
|
272
|
+
return params[:app_is_loaded_flag]
|
273
|
+
end
|
274
|
+
|
275
|
+
def get_timeout_in_second(params)
|
276
|
+
return DEFAULT_TIMEOUT_IN_SECONDS if params[:timeout_in_seconds].nil?
|
277
|
+
return params[:timeout_in_seconds].to_i
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
#
|
283
|
+
# Represents the browser window the application has been loaded into
|
284
|
+
#
|
285
|
+
class Window
|
286
|
+
|
287
|
+
def initialize(driver)
|
288
|
+
@driver = driver
|
289
|
+
end
|
290
|
+
|
291
|
+
#
|
292
|
+
# Moves the browser window
|
293
|
+
#
|
294
|
+
def move_to(x, y)
|
295
|
+
@driver.sc_window_move_to(x,y)
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# Resizes the browser window
|
300
|
+
#
|
301
|
+
def resize_to(width, height)
|
302
|
+
@driver.sc_window_resize_to(width, height)
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# Maximizes the browser window
|
307
|
+
#
|
308
|
+
def maximize()
|
309
|
+
@driver.sc_window_maximize
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Lebowski
|
2
|
+
module Foundation
|
3
|
+
|
4
|
+
# A SproutCore error instance (SC.Error)
|
5
|
+
SC_T_ERROR = 'error'
|
6
|
+
|
7
|
+
# Null value
|
8
|
+
SC_T_NULL = 'null'
|
9
|
+
|
10
|
+
# Undefined value
|
11
|
+
SC_T_UNDEFINED = 'undefined'
|
12
|
+
|
13
|
+
# A function
|
14
|
+
SC_T_FUNCTION = 'function'
|
15
|
+
|
16
|
+
# Number primitive
|
17
|
+
SC_T_NUMBER = 'number'
|
18
|
+
|
19
|
+
# Boolean primitive
|
20
|
+
SC_T_BOOL = 'boolean'
|
21
|
+
|
22
|
+
# An instance of Array
|
23
|
+
SC_T_ARRAY = 'array'
|
24
|
+
|
25
|
+
# String primitive
|
26
|
+
SC_T_STRING = 'string'
|
27
|
+
|
28
|
+
# A JavaScript object not inheriting from SC.Object
|
29
|
+
SC_T_HASH = 'hash'
|
30
|
+
|
31
|
+
# A SproutCore class (created using SC.Object.extend())
|
32
|
+
SC_T_CLASS = 'class'
|
33
|
+
|
34
|
+
# A SproutCore object instance
|
35
|
+
SC_T_OBJECT = 'object'
|
36
|
+
|
37
|
+
SC_MIXED_STATE = '__MIXED__'
|
38
|
+
|
39
|
+
# Constants used by the collection view. see SproutCore file collection_content.js
|
40
|
+
SC_LEAF_NODE = 0x0020
|
41
|
+
SC_BRANCH_OPEN = 0x0011
|
42
|
+
SC_BRANCH_CLOSED = 0x0012
|
43
|
+
|
44
|
+
module Util
|
45
|
+
|
46
|
+
def assert_is_object(value, name)
|
47
|
+
if not value.kind_of? Lebowski::Foundation::ProxyObject
|
48
|
+
raise ArgumentInvalidTypeError.new name, value, Lebowski::Foundation::ProxyObject
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def assert_is_view(value, name)
|
53
|
+
if not value.kind_of? Lebowski::Foundation::Views::View
|
54
|
+
raise ArgumentInvalidTypeError.new name, value, Lebowski::Foundation::Views::View
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
# ==========================================================================
|
2
|
+
# Project: Lebowski Framework - The SproutCore Test Automation Framework
|
3
|
+
# License: Licensed under MIT license (see License.txt)
|
4
|
+
# ==========================================================================
|
5
|
+
|
6
|
+
module Lebowski
|
7
|
+
module Foundation
|
8
|
+
|
9
|
+
#
|
10
|
+
# Represents a SproutCore Core Query object. This proxy provides a subset of the
|
11
|
+
# functionality that the actual core query object has.
|
12
|
+
#
|
13
|
+
# The core query is obtained through a view object and requires a CSS selector.
|
14
|
+
# Based on the associated view and given selector, the core query object will
|
15
|
+
# then contain zero or more DOM elements that match the selector starting from
|
16
|
+
# the view's layer (read: root DOM element).
|
17
|
+
#
|
18
|
+
# For feature and integration testing, the use of the core query object may be
|
19
|
+
# too low-level. Rather, this object is handy for custom views that override
|
20
|
+
# the render method. By creating a proxy to the custom view you can then use
|
21
|
+
# this object to do some fine grained checks that you don't want to expose
|
22
|
+
# to the casual tester, for instance.
|
23
|
+
#
|
24
|
+
class CoreQuery
|
25
|
+
|
26
|
+
INVALID_HANDLE = -1
|
27
|
+
|
28
|
+
attr_reader :selector, # The CSS selector
|
29
|
+
:handle, # The handle to the remote core query object
|
30
|
+
:abs_path # The absolute path to the view this object comes from
|
31
|
+
|
32
|
+
#
|
33
|
+
# Creates an instance. Once created, it will have a handle to the remote
|
34
|
+
# core query object in order to perform subsequent calls. Call the done()
|
35
|
+
# method when this object is no longer used
|
36
|
+
#
|
37
|
+
# @param abs_path {String} a property path to the view the core query object will come from
|
38
|
+
# @param selector {String} a CSS selector. See SproutCore's CoreQuery object for more details
|
39
|
+
# @param driver {Object} driver to communicate with the selenium server
|
40
|
+
#
|
41
|
+
def initialize(abs_path, selector, driver)
|
42
|
+
@abs_path = abs_path
|
43
|
+
@selector = selector.nil? ? "" : selector
|
44
|
+
@driver = driver
|
45
|
+
@handle = INVALID_HANDLE
|
46
|
+
@size = 0
|
47
|
+
|
48
|
+
@handle = @driver.get_sc_core_query(abs_path, selector)
|
49
|
+
@size = @driver.get_sc_core_query_size(@handle) if has_handle?
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Returns the number of elements found by this core query object
|
54
|
+
#
|
55
|
+
def size()
|
56
|
+
return @size if has_handle?
|
57
|
+
return -1
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Checks if this object has a handle to the remote core query object
|
62
|
+
#
|
63
|
+
def has_handle?()
|
64
|
+
return (not @handle == INVALID_HANDLE)
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Will clean up this object when no longer used
|
69
|
+
#
|
70
|
+
def done()
|
71
|
+
@driver.sc_core_query_done(@handle)
|
72
|
+
@handle = INVALID_HANDLE
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Get an element at a given index. Returns an instance of DOMElement
|
77
|
+
#
|
78
|
+
# @param index {Number} returns element if this object has a handle and
|
79
|
+
# the index is within range
|
80
|
+
#
|
81
|
+
def [](index)
|
82
|
+
if has_handle? and (index > -1) and (index <= (@size - 1))
|
83
|
+
return Lebowski::Foundation::DOMElement.new @handle, index, @driver
|
84
|
+
end
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Used to iterate through each element in this object. The block provided
|
90
|
+
# will be provided to argments: the element and its index. You can use this
|
91
|
+
# method as follows:
|
92
|
+
#
|
93
|
+
# core_query.each do |element, index |
|
94
|
+
# ...
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
def each(&block)
|
98
|
+
return if (not has_handle? or not block_given? or size <= 0)
|
99
|
+
|
100
|
+
for i in 0..size - 1 do
|
101
|
+
elem = Lebowski::Foundation::DOMElement.new @handle, i, @driver
|
102
|
+
yield elem, i
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Used to fetch elements from this object. The block provided
|
108
|
+
# is used to return an element that will be added to the array
|
109
|
+
# of elements to be returned. If the block does not return an
|
110
|
+
# element then the element will not be added to the resulting
|
111
|
+
# array. As an example:
|
112
|
+
#
|
113
|
+
# elements = core_query.fetch { |element, index| element if element.text == 'foo' }
|
114
|
+
#
|
115
|
+
# The result array will then contain all elements in the core query
|
116
|
+
# object that have text equal to 'foo'. if no elements match then
|
117
|
+
# an empty array is returned.
|
118
|
+
#
|
119
|
+
# The block provided is to have the following setup:
|
120
|
+
#
|
121
|
+
# do |element, index| OR { |element, index| ... }
|
122
|
+
# ...
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
def fetch(&block)
|
126
|
+
return [] if not block_given?
|
127
|
+
elems = []
|
128
|
+
each do |elem, index|
|
129
|
+
result = yield elem, index
|
130
|
+
elems << result if not result.nil?
|
131
|
+
end
|
132
|
+
return elems
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Used to perform a check on the elements from this core query. The
|
137
|
+
# block provided is used to return true or false based of if the
|
138
|
+
# given element passed some condition. In addition to the block
|
139
|
+
# supplied to this method, you also pass in a condition about the
|
140
|
+
# check being perform, which can be one of the following:
|
141
|
+
#
|
142
|
+
# :all - Check that all elements meet the block's checks
|
143
|
+
# :any - Check that one or more elements meet the block's checks
|
144
|
+
# :none - Check that no elements meet the block's checks
|
145
|
+
# :one - Check that there is only one element that meets the block's checks
|
146
|
+
#
|
147
|
+
# If no condition argument is gien this :all is the default.
|
148
|
+
#
|
149
|
+
# Here is an example of how to use this method:
|
150
|
+
#
|
151
|
+
# meets_condition = core_query.check :all, do |elem, index|
|
152
|
+
# if elem.text == 'foo'
|
153
|
+
# true # element passes check
|
154
|
+
# else
|
155
|
+
# false # element does not pass check
|
156
|
+
# end
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# @see #all?
|
160
|
+
# @see #any?
|
161
|
+
# @see #none?
|
162
|
+
# @see #one?
|
163
|
+
#
|
164
|
+
def check(condition=nil, &block)
|
165
|
+
return false if not block_given?
|
166
|
+
counter = 0
|
167
|
+
each do |elem, index|
|
168
|
+
result = yield elem, index
|
169
|
+
counter = counter + 1 if result == true
|
170
|
+
end
|
171
|
+
|
172
|
+
case condition
|
173
|
+
when :all
|
174
|
+
return counter == size
|
175
|
+
when :any
|
176
|
+
return counter > 0
|
177
|
+
when :none
|
178
|
+
return counter == 0
|
179
|
+
when :one
|
180
|
+
return counter == 1
|
181
|
+
else
|
182
|
+
return counter == size
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
#
|
187
|
+
# Used to check if all of the element for this core query meet
|
188
|
+
# the conditions for the given block
|
189
|
+
#
|
190
|
+
# @see #check
|
191
|
+
#
|
192
|
+
def all?(&block)
|
193
|
+
check :all &block
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# Used to check if any of the element for this core query meet
|
198
|
+
# the conditions for the given block
|
199
|
+
#
|
200
|
+
# @see #check
|
201
|
+
#
|
202
|
+
def any?(&block)
|
203
|
+
check :any &block
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# Used to check if none of the element for this core query meet
|
208
|
+
# the conditions for the given block
|
209
|
+
#
|
210
|
+
# @see #check
|
211
|
+
#
|
212
|
+
def none?(&block)
|
213
|
+
check :none &block
|
214
|
+
end
|
215
|
+
|
216
|
+
#
|
217
|
+
# Used to check if there is only one element for this core query that
|
218
|
+
# meets the conditions for the given block
|
219
|
+
#
|
220
|
+
# @see #check
|
221
|
+
#
|
222
|
+
def one?(&block)
|
223
|
+
check :one &block
|
224
|
+
end
|
225
|
+
|
226
|
+
alias_method :element, :[]
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
end
|