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,18 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/scui/views/date_picker')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/scui/views/combo_box')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/scui/views/linkit')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/scui/mixins/node_item_view_support')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/scui/mixins/terminal_view_support')
|
6
|
+
|
7
|
+
module Lebowski
|
8
|
+
module SCUI
|
9
|
+
module Views
|
10
|
+
include Lebowski::Foundation
|
11
|
+
|
12
|
+
ProxyFactory.proxy DatePickerView
|
13
|
+
ProxyFactory.proxy ComboBoxView
|
14
|
+
ProxyFactory.proxy CanvasView
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Lebowski
|
2
|
+
module SCUI
|
3
|
+
module Mixins
|
4
|
+
|
5
|
+
module NodeItemViewSupport
|
6
|
+
include Lebowski::Foundation::Mixins::CollectionItemViewSupport
|
7
|
+
|
8
|
+
def has_node_item_view_support
|
9
|
+
return true
|
10
|
+
end
|
11
|
+
|
12
|
+
def terminal_by_name(name)
|
13
|
+
terminal = terminals.find_first({ :terminal => name })
|
14
|
+
raise ArgumentError.new "There is no terminal with the name #{name}." if terminal.nil?
|
15
|
+
return terminal
|
16
|
+
end
|
17
|
+
|
18
|
+
def terminals
|
19
|
+
@terminals = Support::TerminalViewArray.new(self) if @terminals.nil?
|
20
|
+
return @terminals
|
21
|
+
end
|
22
|
+
|
23
|
+
def drag_to_coordinates(x, y)
|
24
|
+
coord_x = -1*(self.position.x) + self.frame.width + x
|
25
|
+
coord_y = -1*(self.position.y) + self.frame.height + y
|
26
|
+
|
27
|
+
self.drag(coord_x, coord_y)
|
28
|
+
end
|
29
|
+
|
30
|
+
def drag_to_node(item)
|
31
|
+
fixed_node = get_fixed_node(item)
|
32
|
+
self.drag_on_to(fixed_node)
|
33
|
+
end
|
34
|
+
|
35
|
+
def drag_before_node(item)
|
36
|
+
drag_relative_to_node(item, true, -1)
|
37
|
+
end
|
38
|
+
|
39
|
+
def drag_after_node(item)
|
40
|
+
drag_relative_to_node(item, true)
|
41
|
+
end
|
42
|
+
|
43
|
+
def drag_above_node(item)
|
44
|
+
drag_relative_to_node(item, false, -1)
|
45
|
+
end
|
46
|
+
|
47
|
+
def drag_below_node(item)
|
48
|
+
drag_relative_to_node(item, false)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def get_fixed_node(item)
|
53
|
+
if item.kind_of? Integer
|
54
|
+
fixed_node = @parent.item_views[item]
|
55
|
+
raise ArgumentError.new "There is no node at index #{item}" if fixed_node.nil?
|
56
|
+
return fixed_node
|
57
|
+
else
|
58
|
+
assert_item_has_node_item_view_support(item)
|
59
|
+
return item
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def drag_relative_to_node(item, horizontal_drag, multiplier = 1)
|
64
|
+
fixed_node = get_fixed_node(item)
|
65
|
+
|
66
|
+
x = horizontal_drag ? (fixed_node.frame.width + 50) * multiplier : 0
|
67
|
+
y = horizontal_drag ? 0 : (fixed_node.frame.height + 50) * multiplier
|
68
|
+
|
69
|
+
self.drag_to(fixed_node, x, y)
|
70
|
+
end
|
71
|
+
|
72
|
+
def assert_item_has_node_item_view_support(item)
|
73
|
+
if not item.respond_to? :has_node_item_view_support
|
74
|
+
raise ArgumentError.new "The item passed in must have node item view support (#{NodeItemViewSupport})"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module Support
|
79
|
+
|
80
|
+
class TerminalViewArray < Lebowski::Foundation::ObjectArray
|
81
|
+
def initialize(parent, *params)
|
82
|
+
if params.empty?
|
83
|
+
super(parent, 'childViews', 'length', { :prefilter => { :isTerminal => true } })
|
84
|
+
else
|
85
|
+
super(parent, 'childViews', 'length', *params)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_object(index, expected_type=nil)
|
90
|
+
rel_path = "#{@array_rel_path}.#{index}"
|
91
|
+
obj = @parent[rel_path, expected_type]
|
92
|
+
|
93
|
+
mix_in_support_for_object obj
|
94
|
+
return obj
|
95
|
+
end
|
96
|
+
|
97
|
+
def mix_in_support_for_object(obj)
|
98
|
+
if not obj.class.ancestors.member? Lebowski::SCUI::Mixins::TerminalViewSupport
|
99
|
+
obj.extend Lebowski::SCUI::Mixins::TerminalViewSupport
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_filtered_object_array(parent, array_rel_path, array_length_property_name, prefilter)
|
104
|
+
klass = self.class
|
105
|
+
return klass.new parent, prefilter
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class LinksArray < Lebowski::Foundation::ObjectArray
|
110
|
+
def initialize(parent)
|
111
|
+
links_key = parent['content.linksKey']
|
112
|
+
super(parent, "content.#{links_key}")
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_object(index, expected_type=nil)
|
116
|
+
rel_path = "#{@array_rel_path}.#{index}"
|
117
|
+
obj = @parent[rel_path, expected_type]
|
118
|
+
|
119
|
+
mix_in_support_for_object obj
|
120
|
+
return obj
|
121
|
+
end
|
122
|
+
|
123
|
+
def mix_in_support_for_object(obj)
|
124
|
+
if not obj.class.ancestors.member? Lebowski::SCUI::Mixins::LinkSupport
|
125
|
+
obj.extend Lebowski::SCUI::Mixins::LinkSupport
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Lebowski
|
2
|
+
module SCUI
|
3
|
+
module Mixins
|
4
|
+
|
5
|
+
module TerminalViewSupport
|
6
|
+
def has_terminal_view_support
|
7
|
+
return true
|
8
|
+
end
|
9
|
+
|
10
|
+
def link_to(end_term, x = 0, y = 0)
|
11
|
+
assert_item_has_terminal_view_support(end_term)
|
12
|
+
self.drag_to(end_term, x, y)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def assert_item_has_terminal_view_support(item)
|
17
|
+
if not item.respond_to? :has_terminal_view_support
|
18
|
+
raise ArgumentError.new "Cannot link to an item without terminal view support (#{TerminalViewSupport})"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Lebowski
|
2
|
+
module SCUI
|
3
|
+
module Views
|
4
|
+
|
5
|
+
class ComboBoxList
|
6
|
+
attr_reader :item_views
|
7
|
+
|
8
|
+
def initialize(parent)
|
9
|
+
@parent = parent
|
10
|
+
@list_pane = parent['_listPane']
|
11
|
+
|
12
|
+
list_view_path = 'contentView.listView.contentView'
|
13
|
+
if not @list_pane.sc_path_defined?(list_view_path)
|
14
|
+
# revert to the old path to access the list view
|
15
|
+
list_view_path = 'contentView.contentView'
|
16
|
+
end
|
17
|
+
|
18
|
+
@value_key = @list_pane["#{list_view_path}.contentValueKey"]
|
19
|
+
@item_views = @list_pane[list_view_path].item_views
|
20
|
+
end
|
21
|
+
|
22
|
+
def count?(expected_count, item)
|
23
|
+
type(item)
|
24
|
+
return (@item_views.count == expected_count)
|
25
|
+
end
|
26
|
+
|
27
|
+
def any?(item)
|
28
|
+
type(item)
|
29
|
+
return @item_views.any?({@value_key => item})
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :some?, :any?
|
33
|
+
|
34
|
+
def one?(item)
|
35
|
+
type(item)
|
36
|
+
return @item_views.one?({@value_key => item})
|
37
|
+
end
|
38
|
+
|
39
|
+
def none?(item)
|
40
|
+
type(item)
|
41
|
+
@item_views.none?({@value_key => item})
|
42
|
+
end
|
43
|
+
|
44
|
+
def list_displayed?
|
45
|
+
return @list_pane.isPaneAttached
|
46
|
+
end
|
47
|
+
|
48
|
+
def select_item(item)
|
49
|
+
@parent.display_list
|
50
|
+
if item.kind_of? Integer
|
51
|
+
select_item_by_index(item)
|
52
|
+
elsif item.kind_of? String
|
53
|
+
select_item_by_name(/^#{item}/i)
|
54
|
+
elsif item.kind_of? Regexp
|
55
|
+
select_item_by_name(item)
|
56
|
+
end
|
57
|
+
@parent.hide_list
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def select_item_by_index(index)
|
62
|
+
raise ArgumentError.new "Index out of range. The item number must be greater than or equal to zero." if (index < 0)
|
63
|
+
raise ArgumentError.new "Index out of range. There are fewer than #{index.to_s} items in the list." if (index >= @item_views.count)
|
64
|
+
@item_views[index].select
|
65
|
+
end
|
66
|
+
|
67
|
+
def select_item_by_name(name)
|
68
|
+
if one?(name)
|
69
|
+
@item_views.find_first({@value_key => name}).select
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def type(text)
|
74
|
+
field = @parent.child_views[0]
|
75
|
+
if text.kind_of? Regexp
|
76
|
+
field.type_keys(text.inspect.tr('/^', '').tr('/i', ''))
|
77
|
+
else
|
78
|
+
field.type_keys(text)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class ComboBoxView < Lebowski::Foundation::Views::View
|
84
|
+
representing_sc_class 'SCUI.ComboBoxView'
|
85
|
+
|
86
|
+
def empty?
|
87
|
+
val = self['value']
|
88
|
+
return (val.nil? or val.empty?)
|
89
|
+
end
|
90
|
+
|
91
|
+
def display_list
|
92
|
+
click_button if !list.list_displayed?
|
93
|
+
end
|
94
|
+
|
95
|
+
def hide_list
|
96
|
+
click_button if list.list_displayed?
|
97
|
+
end
|
98
|
+
|
99
|
+
def list_displayed?
|
100
|
+
return list.list_displayed?
|
101
|
+
end
|
102
|
+
|
103
|
+
def select_item(item)
|
104
|
+
list.select_item(item)
|
105
|
+
end
|
106
|
+
|
107
|
+
def list
|
108
|
+
return ComboBoxList.new(self)
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def click_button
|
113
|
+
self['dropDownButtonView'].click
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Lebowski
|
4
|
+
module SCUI
|
5
|
+
module Views
|
6
|
+
|
7
|
+
class DatePickerCalendar
|
8
|
+
def initialize(parent)
|
9
|
+
@today_button = parent['_calendar_popup.contentView.todayButton']
|
10
|
+
@none_button = parent['_calendar_popup.contentView.noneButton']
|
11
|
+
@calendar = parent['_calendar_popup.contentView.calendar']
|
12
|
+
@parent = parent
|
13
|
+
end
|
14
|
+
|
15
|
+
def date_selected?(date)
|
16
|
+
curr_year = @calendar['selectedDate.year']
|
17
|
+
curr_month = @calendar['selectedDate.month']
|
18
|
+
curr_day = @calendar['selectedDate.day']
|
19
|
+
|
20
|
+
if date.nil?
|
21
|
+
return false if !(curr_month.nil? && curr_day.nil? && curr_year.nil?)
|
22
|
+
else
|
23
|
+
return false if !((curr_month == date.month) && (curr_day == date.day) && (curr_year == date.year))
|
24
|
+
end
|
25
|
+
return true
|
26
|
+
end
|
27
|
+
|
28
|
+
def showing_month?(month)
|
29
|
+
month_displayed = @calendar['monthStartOn.month'] - 1
|
30
|
+
return @calendar['monthStrings'][month_displayed] == month
|
31
|
+
end
|
32
|
+
|
33
|
+
def showing_year?(year)
|
34
|
+
year_displayed = @calendar['monthStartOn.year']
|
35
|
+
return year_displayed == year
|
36
|
+
end
|
37
|
+
|
38
|
+
def select_date(date)
|
39
|
+
raise ArgumentError.new "A DateTime object must be provided to the pick_date method." if !(date.class == DateTime || date.class == Time)
|
40
|
+
|
41
|
+
if @calendar['selectedDate'].nil?
|
42
|
+
year_displayed = @calendar['monthStartOn.year']
|
43
|
+
month_displayed = @calendar['monthStartOn.month']
|
44
|
+
else
|
45
|
+
year_displayed = @calendar['selectedDate.year']
|
46
|
+
month_displayed = @calendar['selectedDate.month']
|
47
|
+
end
|
48
|
+
|
49
|
+
year_diff = date.year - year_displayed
|
50
|
+
month_diff = date.month - month_displayed
|
51
|
+
|
52
|
+
date_diff = year_diff * 12 + month_diff
|
53
|
+
|
54
|
+
if date_diff > 0 #date in the future
|
55
|
+
date_diff.abs.times { select_next_month }
|
56
|
+
elsif date_diff < 0 #date in the past
|
57
|
+
date_diff.abs.times { select_previous_month }
|
58
|
+
else
|
59
|
+
@parent.display_calendar
|
60
|
+
end
|
61
|
+
|
62
|
+
date_int = date.day + @calendar['monthStartOn.dayOfWeek'] + 1
|
63
|
+
@calendar.child_views[date_int].click
|
64
|
+
end
|
65
|
+
|
66
|
+
def select_previous_month
|
67
|
+
@parent.display_calendar
|
68
|
+
prev_month = @calendar.child_views[0]
|
69
|
+
prev_month.click
|
70
|
+
end
|
71
|
+
|
72
|
+
def select_next_month
|
73
|
+
@parent.display_calendar
|
74
|
+
next_month = @calendar.child_views[1]
|
75
|
+
next_month.click
|
76
|
+
end
|
77
|
+
|
78
|
+
def select_none
|
79
|
+
@parent.display_calendar
|
80
|
+
@none_button.click
|
81
|
+
end
|
82
|
+
|
83
|
+
def select_today
|
84
|
+
@parent.display_calendar
|
85
|
+
@today_button.click
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class DatePickerView < Lebowski::Foundation::Views::View
|
90
|
+
representing_sc_class 'SCUI.DatePickerView'
|
91
|
+
|
92
|
+
def date_selected?(date)
|
93
|
+
return calendar.date_selected?(date)
|
94
|
+
end
|
95
|
+
|
96
|
+
def showing_month?(month)
|
97
|
+
return calendar.showing_month?(month)
|
98
|
+
end
|
99
|
+
|
100
|
+
def showing_year?(year)
|
101
|
+
return calendar.showing_year?(year)
|
102
|
+
end
|
103
|
+
|
104
|
+
def select_date(date)
|
105
|
+
calendar.select_date(date)
|
106
|
+
end
|
107
|
+
|
108
|
+
def select_previous_month
|
109
|
+
calendar.select_previous_month
|
110
|
+
end
|
111
|
+
|
112
|
+
def select_next_month
|
113
|
+
calendar.select_next_month
|
114
|
+
end
|
115
|
+
|
116
|
+
def select_none
|
117
|
+
calendar.select_none
|
118
|
+
end
|
119
|
+
|
120
|
+
def select_today
|
121
|
+
calendar.select_today
|
122
|
+
end
|
123
|
+
|
124
|
+
def today_selected?
|
125
|
+
return date_selected?(Time.now)
|
126
|
+
end
|
127
|
+
|
128
|
+
def display_calendar
|
129
|
+
click_button if !self['isShowingCalendar']
|
130
|
+
end
|
131
|
+
|
132
|
+
def hide_calendar
|
133
|
+
click_button if self['isShowingCalendar']
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def calendar
|
138
|
+
@calendar = DatePickerCalendar.new(self) if @calendar.nil?
|
139
|
+
return @calendar
|
140
|
+
end
|
141
|
+
|
142
|
+
def click_button
|
143
|
+
self['_date_button'].click
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|