lebowski 0.1.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/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,38 @@
|
|
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
|
+
class SCObject < ProxyObject
|
10
|
+
|
11
|
+
@@represented_sc_classes = {}
|
12
|
+
|
13
|
+
def self.representing_sc_class(sc_class)
|
14
|
+
raise ArgumentError "sc_class must be a non-empty string" if (not sc_class.kind_of? String) or sc_class.empty?
|
15
|
+
return if @@represented_sc_classes.has_key? self.to_s
|
16
|
+
@@represented_sc_classes[self.to_s] = sc_class
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.represented_sc_class
|
20
|
+
return @@represented_sc_classes[self.to_s]
|
21
|
+
end
|
22
|
+
|
23
|
+
def represented_sc_class
|
24
|
+
return @@represented_sc_classes[self.class.to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_represented_sc_class?()
|
28
|
+
return (not represented_sc_class.nil?)
|
29
|
+
end
|
30
|
+
|
31
|
+
def kind_of_represented_sc_class?()
|
32
|
+
return false if (not has_represented_sc_class?)
|
33
|
+
return sc_kind_of?(represented_sc_class)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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
|
+
module Views
|
9
|
+
|
10
|
+
#
|
11
|
+
# Represents a proxy to a SproutCore button view (SC.ButtonView)
|
12
|
+
#
|
13
|
+
class ButtonView < Lebowski::Foundation::Views::View
|
14
|
+
|
15
|
+
representing_sc_class 'SC.ButtonView'
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,63 @@
|
|
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
|
+
module Views
|
9
|
+
|
10
|
+
#
|
11
|
+
# Represents a proxy to a SproutCore button view (SC.CheckboxView)
|
12
|
+
#
|
13
|
+
class CheckboxView < Lebowski::Foundation::Views::View
|
14
|
+
|
15
|
+
representing_sc_class 'SC.CheckboxView'
|
16
|
+
|
17
|
+
# A value the view's isSelected property can return other than a boolean value
|
18
|
+
MIXED_STATE = '__MIXED__'
|
19
|
+
|
20
|
+
#
|
21
|
+
# @override
|
22
|
+
#
|
23
|
+
# Need to perform a basic click so that the view will respond correctly
|
24
|
+
#
|
25
|
+
def click()
|
26
|
+
mouse_down
|
27
|
+
mouse_up
|
28
|
+
basic_click
|
29
|
+
stall :click
|
30
|
+
end
|
31
|
+
|
32
|
+
def deselect()
|
33
|
+
if in_mixed_state?
|
34
|
+
click
|
35
|
+
click
|
36
|
+
elsif is_selected?
|
37
|
+
click
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def select()
|
42
|
+
click if (not is_selected?) or in_mixed_state?
|
43
|
+
end
|
44
|
+
|
45
|
+
def is_selected?()
|
46
|
+
val = self['isSelected']
|
47
|
+
return (val == true or val == MIXED_STATE)
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :is_checked?, :is_selected?
|
51
|
+
|
52
|
+
#
|
53
|
+
# Used to check if this view is in a mixed state. The view is in
|
54
|
+
# a mixed state if it has assigned value but nothing is selected
|
55
|
+
#
|
56
|
+
def in_mixed_state?()
|
57
|
+
return (self['isSelected'] == MIXED_STATE)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,304 @@
|
|
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
|
+
module Views
|
10
|
+
|
11
|
+
#
|
12
|
+
# Represents a proxy to a generic SproutCore collection view (SC.CollectionView)
|
13
|
+
#
|
14
|
+
class CollectionView < Lebowski::Foundation::Views::View
|
15
|
+
include Lebowski::Foundation
|
16
|
+
|
17
|
+
representing_sc_class 'SC.CollectionView'
|
18
|
+
|
19
|
+
def allowed_content_reordering?()
|
20
|
+
return self['canReorderContent']
|
21
|
+
end
|
22
|
+
|
23
|
+
def allowed_content_deletion?()
|
24
|
+
return self['canDeleteContent']
|
25
|
+
end
|
26
|
+
|
27
|
+
def allowed_content_editing?()
|
28
|
+
return self['canEditContent']
|
29
|
+
end
|
30
|
+
|
31
|
+
def allowed_deselect_all?()
|
32
|
+
return self['allowDeselectAll']
|
33
|
+
end
|
34
|
+
|
35
|
+
def content()
|
36
|
+
@content = create_content_object_array if @content.nil?
|
37
|
+
return @content
|
38
|
+
end
|
39
|
+
|
40
|
+
def item_views()
|
41
|
+
@item_views = create_item_views_object_array if @item_views.nil?
|
42
|
+
return @item_views
|
43
|
+
end
|
44
|
+
|
45
|
+
def can_drag_to_start_of?()
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
49
|
+
def can_drag_to_end_of?()
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
|
53
|
+
def apply_drag_to_start_of(source)
|
54
|
+
# no-op
|
55
|
+
end
|
56
|
+
|
57
|
+
def apply_drag_to_end_of(source)
|
58
|
+
# no-op
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def create_content_object_array()
|
64
|
+
return Support::CollectionItemArray.new self
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_item_views_object_array()
|
68
|
+
return Support::CollectionItemViewArray.new self
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
module Support
|
74
|
+
|
75
|
+
# Represents a generic array of content objects for a collection view
|
76
|
+
class CollectionItemArray < Lebowski::Foundation::ObjectArray
|
77
|
+
include Lebowski::Foundation
|
78
|
+
|
79
|
+
def initialize(parent, *params)
|
80
|
+
super(parent, 'content', 'length', *params)
|
81
|
+
end
|
82
|
+
|
83
|
+
def selected()
|
84
|
+
@selected = self.filter({ :is_selected => true }) if @selected.nil?
|
85
|
+
return @selected
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def create_filtered_object_array(parent, array_rel_path, array_length_property_name, prefilter)
|
91
|
+
klass = self.class
|
92
|
+
return klass.new parent, prefilter
|
93
|
+
end
|
94
|
+
|
95
|
+
def init_validate_parent(parent)
|
96
|
+
if not parent.kind_of? CollectionView
|
97
|
+
raise ArgumentInvalidTypeError.new "parent", parent, CollectionView
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def item_is_selected?(index)
|
102
|
+
return @driver.get_sc_collection_view_content_is_selected(@parent.abs_path, index)
|
103
|
+
end
|
104
|
+
|
105
|
+
def item_is_group?(index)
|
106
|
+
return @driver.get_sc_collection_view_content_is_group(@parent.abs_path, index)
|
107
|
+
end
|
108
|
+
|
109
|
+
def item_outline_level(index)
|
110
|
+
return @driver.get_sc_collection_view_content_outline_level(@parent.abs_path, index)
|
111
|
+
end
|
112
|
+
|
113
|
+
def item_disclosure_state(index)
|
114
|
+
return @driver.get_sc_collection_view_content_disclosure_state(@parent.abs_path, index)
|
115
|
+
end
|
116
|
+
|
117
|
+
# @override
|
118
|
+
#
|
119
|
+
# Handle special flags
|
120
|
+
def find_indexes_process_filter(filter)
|
121
|
+
processed_filter = {}
|
122
|
+
|
123
|
+
@item_is_selected_flag = :no_flag
|
124
|
+
@item_is_group_flag = :no_flag
|
125
|
+
@item_outline_level_flag = :no_flag
|
126
|
+
@item_disclosure_state_flag = :no_flag
|
127
|
+
|
128
|
+
filter.each do |key, value|
|
129
|
+
case key
|
130
|
+
when :is_selected
|
131
|
+
@item_is_selected_flag = value
|
132
|
+
when :is_group
|
133
|
+
@item_is_group_flag = value
|
134
|
+
when :outline_level
|
135
|
+
@item_outline_level_flag = value
|
136
|
+
when :disclosure_state
|
137
|
+
@item_disclosure_state_flag = value
|
138
|
+
else
|
139
|
+
processed_filter[key] = value
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
return processed_filter
|
144
|
+
end
|
145
|
+
|
146
|
+
# @override
|
147
|
+
#
|
148
|
+
# Handle special flags
|
149
|
+
def find_indexes_process_indexes(indexes)
|
150
|
+
processed_indexes = []
|
151
|
+
|
152
|
+
indexes.each do |index|
|
153
|
+
if @item_is_selected_flag != :no_flag
|
154
|
+
next if item_is_selected?(index) != @item_is_selected_flag
|
155
|
+
end
|
156
|
+
|
157
|
+
if @item_is_group_flag != :no_flag
|
158
|
+
next if item_is_group?(index) != @item_is_group_flag
|
159
|
+
end
|
160
|
+
|
161
|
+
if @item_outline_level_flag != :no_flag
|
162
|
+
next if item_outline_level(index) != @item_outline_level_flag
|
163
|
+
end
|
164
|
+
|
165
|
+
if @item_disclosure_state_flag != :no_flag
|
166
|
+
next if item_disclosure_state(index) != @item_disclosure_state_flag
|
167
|
+
end
|
168
|
+
|
169
|
+
processed_indexes << index
|
170
|
+
end
|
171
|
+
|
172
|
+
return processed_indexes
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
# Represents a generic array of item views for a collection view
|
178
|
+
class CollectionItemViewArray < CollectionItemArray
|
179
|
+
include Lebowski::Foundation
|
180
|
+
include Lebowski::Foundation::Views
|
181
|
+
|
182
|
+
SELECT_ALL_KEY = 'a'
|
183
|
+
|
184
|
+
def index_of(obj)
|
185
|
+
indexes = find_indexes({ :sc_guid => obj.content.sc_guid })
|
186
|
+
return indexes.empty? ? -1 : indexes[0]
|
187
|
+
end
|
188
|
+
|
189
|
+
def find_with_content(content)
|
190
|
+
if content.nil?
|
191
|
+
raise ArgumentError.new "content can not be nil"
|
192
|
+
end
|
193
|
+
|
194
|
+
content = [content] if (not content.kind_of? Array)
|
195
|
+
|
196
|
+
items = []
|
197
|
+
content.each do |obj|
|
198
|
+
if not obj.kind_of? Lebowski::Foundation::ProxyObject
|
199
|
+
raise ArgumentInvalidTypeError.new "content", obj, Lebowski::Foundation::ProxyObject
|
200
|
+
end
|
201
|
+
|
202
|
+
guid = obj.sc_guid
|
203
|
+
result = find_all({ :sc_guid => guid })
|
204
|
+
items << result[0] if (not result.empty?)
|
205
|
+
end
|
206
|
+
return items
|
207
|
+
end
|
208
|
+
|
209
|
+
def select(filter)
|
210
|
+
raise ArgumentError.new "filter required" if filter.nil?
|
211
|
+
deselect_all
|
212
|
+
select_with_fiter(filter)
|
213
|
+
end
|
214
|
+
|
215
|
+
def select_add(filter)
|
216
|
+
raise ArgumentError.new "filter required" if filter.nil?
|
217
|
+
select_with_fiter(filter)
|
218
|
+
end
|
219
|
+
|
220
|
+
def select_range(val1, val2)
|
221
|
+
idx1 = get_index(val1, 'val1')
|
222
|
+
idx2 = get_index(val2, 'val2')
|
223
|
+
items_count = @parent.item_views.count
|
224
|
+
if (idx1 < 0 or idx1 >= items_count) or (idx2 < 0 or idx2 >= items_count)
|
225
|
+
raise ArgumentError.new "arguments are out of bounds"
|
226
|
+
end
|
227
|
+
item1 = @parent.item_views[idx1]
|
228
|
+
item2 = @parent.item_views[idx2]
|
229
|
+
item1.click
|
230
|
+
@parent.key_down :shift_key
|
231
|
+
item1.select
|
232
|
+
item2.select
|
233
|
+
@parent.key_up :shift_key
|
234
|
+
end
|
235
|
+
|
236
|
+
def deselect(filter)
|
237
|
+
raise ArgumentError.new "filter required" if filter.nil?
|
238
|
+
|
239
|
+
@parent.key_down :ctrl_key
|
240
|
+
each filter do |view, index|
|
241
|
+
view.deselect
|
242
|
+
end
|
243
|
+
@parent.key_up :ctrl_key
|
244
|
+
end
|
245
|
+
|
246
|
+
def select_all()
|
247
|
+
num_views = count
|
248
|
+
return if (num_views == 0)
|
249
|
+
|
250
|
+
if num_views > 1
|
251
|
+
select_range(self[0], self[num_views - 1])
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def deselect_all()
|
256
|
+
@parent.click
|
257
|
+
end
|
258
|
+
|
259
|
+
protected
|
260
|
+
|
261
|
+
# @Override
|
262
|
+
#
|
263
|
+
# Will mixin collection view support for returned proxy
|
264
|
+
def create_object(index, expected_type=nil)
|
265
|
+
rel_path = "itemViewForContentIndex.#{index}"
|
266
|
+
obj = @parent[rel_path, expected_type]
|
267
|
+
# Before we return the item view we have to make sure the
|
268
|
+
# proxy has collection item view support mixin
|
269
|
+
mix_in_support_for_object obj
|
270
|
+
return obj
|
271
|
+
end
|
272
|
+
|
273
|
+
# Mixes in the CollectionItemViewSupport mixin for the given proxy object.
|
274
|
+
#
|
275
|
+
# This is required since the example view provided to a collection
|
276
|
+
# view can be any type of view; therefore, we can't assume the proxy
|
277
|
+
# representing the view will already have collection item view suppor
|
278
|
+
def mix_in_support_for_object(obj)
|
279
|
+
if not obj.class.ancestors.member? Mixins::CollectionItemViewSupport
|
280
|
+
obj.extend Mixins::CollectionItemViewSupport
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
private
|
285
|
+
|
286
|
+
def get_index(val, val_name)
|
287
|
+
return val if val.kind_of?(Integer)
|
288
|
+
return index_of(val) if val.kind_of?(Lebowski::Foundation::ProxyObject)
|
289
|
+
raise ArgumentInvalidTypeError.new val_name, val, Integer, Lebowski::Foundation::ProxyObject
|
290
|
+
end
|
291
|
+
|
292
|
+
def select_with_fiter(filter)
|
293
|
+
each filter do |view, index|
|
294
|
+
view.select_add
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
@@ -0,0 +1,32 @@
|
|
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
|
+
module Views
|
9
|
+
|
10
|
+
#
|
11
|
+
# Represents a proxy to a SproutCore container view (SC.ContainerView)
|
12
|
+
#
|
13
|
+
class ContainerView < Lebowski::Foundation::Views::View
|
14
|
+
|
15
|
+
representing_sc_class 'SC.ContainerView'
|
16
|
+
|
17
|
+
def empty?()
|
18
|
+
return self['contentView'].nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def showing?(view)
|
22
|
+
if not view.kind_of? View
|
23
|
+
raise ArgumentInvalidTypeError.new "view", view, View
|
24
|
+
end
|
25
|
+
|
26
|
+
return (view == self['contentView'])
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|