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.
Files changed (85) hide show
  1. data/History.md +3 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +84 -0
  4. data/README.md +146 -0
  5. data/Rakefile +42 -0
  6. data/bin/lebowski +26 -0
  7. data/bin/lebowski-spec +29 -0
  8. data/bin/lebowski-start-server +24 -0
  9. data/lib/lebowski.rb +15 -0
  10. data/lib/lebowski/core.rb +35 -0
  11. data/lib/lebowski/foundation.rb +52 -0
  12. data/lib/lebowski/foundation/application.rb +315 -0
  13. data/lib/lebowski/foundation/core.rb +61 -0
  14. data/lib/lebowski/foundation/core_query.rb +231 -0
  15. data/lib/lebowski/foundation/dom_element.rb +114 -0
  16. data/lib/lebowski/foundation/errors/argument_invalid_type.rb +31 -0
  17. data/lib/lebowski/foundation/errors/unexpected_type.rb +30 -0
  18. data/lib/lebowski/foundation/mixins/collection_item_view_support.rb +87 -0
  19. data/lib/lebowski/foundation/mixins/delegate_support.rb +22 -0
  20. data/lib/lebowski/foundation/mixins/inline_text_field_support.rb +29 -0
  21. data/lib/lebowski/foundation/mixins/key_check.rb +35 -0
  22. data/lib/lebowski/foundation/mixins/list_item_view_support.rb +36 -0
  23. data/lib/lebowski/foundation/mixins/positioned_element.rb +20 -0
  24. data/lib/lebowski/foundation/mixins/stall_support.rb +79 -0
  25. data/lib/lebowski/foundation/mixins/user_actions.rb +302 -0
  26. data/lib/lebowski/foundation/mixins/wait_actions.rb +44 -0
  27. data/lib/lebowski/foundation/object_array.rb +305 -0
  28. data/lib/lebowski/foundation/panes/alert.rb +117 -0
  29. data/lib/lebowski/foundation/panes/main.rb +20 -0
  30. data/lib/lebowski/foundation/panes/menu.rb +100 -0
  31. data/lib/lebowski/foundation/panes/modal.rb +21 -0
  32. data/lib/lebowski/foundation/panes/palette.rb +21 -0
  33. data/lib/lebowski/foundation/panes/pane.rb +24 -0
  34. data/lib/lebowski/foundation/panes/panel.rb +25 -0
  35. data/lib/lebowski/foundation/panes/picker.rb +43 -0
  36. data/lib/lebowski/foundation/panes/sheet.rb +21 -0
  37. data/lib/lebowski/foundation/proxy_factory.rb +87 -0
  38. data/lib/lebowski/foundation/proxy_object.rb +670 -0
  39. data/lib/lebowski/foundation/sc_object.rb +38 -0
  40. data/lib/lebowski/foundation/views/button.rb +20 -0
  41. data/lib/lebowski/foundation/views/checkbox.rb +63 -0
  42. data/lib/lebowski/foundation/views/collection.rb +304 -0
  43. data/lib/lebowski/foundation/views/container.rb +32 -0
  44. data/lib/lebowski/foundation/views/disclosure.rb +59 -0
  45. data/lib/lebowski/foundation/views/grid.rb +21 -0
  46. data/lib/lebowski/foundation/views/label.rb +30 -0
  47. data/lib/lebowski/foundation/views/list.rb +67 -0
  48. data/lib/lebowski/foundation/views/list_item.rb +280 -0
  49. data/lib/lebowski/foundation/views/menu_item.rb +27 -0
  50. data/lib/lebowski/foundation/views/radio.rb +32 -0
  51. data/lib/lebowski/foundation/views/segmented.rb +97 -0
  52. data/lib/lebowski/foundation/views/select_field.rb +139 -0
  53. data/lib/lebowski/foundation/views/support/simple_item_array.rb +249 -0
  54. data/lib/lebowski/foundation/views/text_field.rb +108 -0
  55. data/lib/lebowski/foundation/views/view.rb +108 -0
  56. data/lib/lebowski/runtime.rb +7 -0
  57. data/lib/lebowski/runtime/errors/remote_control_command_execution_error.rb +9 -0
  58. data/lib/lebowski/runtime/errors/remote_control_command_timeout_error.rb +9 -0
  59. data/lib/lebowski/runtime/errors/remote_control_error.rb +9 -0
  60. data/lib/lebowski/runtime/errors/selenium_server_error.rb +9 -0
  61. data/lib/lebowski/runtime/object_encoder.rb +123 -0
  62. data/lib/lebowski/runtime/sprout_core_driver.rb +14 -0
  63. data/lib/lebowski/runtime/sprout_core_extensions.rb +600 -0
  64. data/lib/lebowski/scui.rb +18 -0
  65. data/lib/lebowski/scui/mixins/node_item_view_support.rb +136 -0
  66. data/lib/lebowski/scui/mixins/terminal_view_support.rb +25 -0
  67. data/lib/lebowski/scui/views/combo_box.rb +119 -0
  68. data/lib/lebowski/scui/views/date_picker.rb +148 -0
  69. data/lib/lebowski/scui/views/linkit.rb +36 -0
  70. data/lib/lebowski/spec.rb +17 -0
  71. data/lib/lebowski/spec/core.rb +21 -0
  72. data/lib/lebowski/spec/matchers/be.rb +63 -0
  73. data/lib/lebowski/spec/matchers/has.rb +40 -0
  74. data/lib/lebowski/spec/matchers/match_supporters/has_object_function.rb +67 -0
  75. data/lib/lebowski/spec/matchers/match_supporters/has_predicate_with_no_prefix.rb +50 -0
  76. data/lib/lebowski/spec/matchers/match_supporters/has_predicate_with_prefix_has.rb +50 -0
  77. data/lib/lebowski/spec/matchers/match_supporters/match_supporter.rb +29 -0
  78. data/lib/lebowski/spec/matchers/method_missing.rb +24 -0
  79. data/lib/lebowski/spec/operators/operator.rb +20 -0
  80. data/lib/lebowski/spec/operators/that.rb +116 -0
  81. data/lib/lebowski/spec/util.rb +26 -0
  82. data/lib/lebowski/version.rb +17 -0
  83. data/resources/selenium-server.jar +0 -0
  84. data/resources/user-extensions.js +1421 -0
  85. metadata +198 -0
@@ -0,0 +1,114 @@
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 DOM element. Primarily used by the CoreQuery object. Use this
11
+ # object to acquire details about a given element.
12
+ #
13
+ class DOMElement
14
+ include Lebowski::Foundation::Mixins::UserActions
15
+
16
+ attr_reader :handle,
17
+ :index
18
+
19
+ #
20
+ # Create an instance.
21
+ #
22
+ # @param handle {Number} the handle used by a core query object
23
+ # @param index {Number} the index to the element in the core query object
24
+ # @param driver {object} used to communicate with the selenium server
25
+ #
26
+ def initialize(handle, index, driver)
27
+ @handle = handle
28
+ @index = index
29
+ @driver = driver
30
+ end
31
+
32
+ def action_locator_args()
33
+ return [@handle, @index]
34
+ end
35
+
36
+ def action_target()
37
+ return :core_query_element
38
+ end
39
+
40
+ #
41
+ # Returns the classes of the element as a string
42
+ #
43
+ def classes()
44
+ return @driver.get_sc_core_query_element_classes(@handle, @index)
45
+ end
46
+
47
+ #
48
+ # Checks if this DOM element has a given CSS class
49
+ #
50
+ # @return true if the element has the class, otherwise false is returned
51
+ #
52
+ def has_class?(klass)
53
+ return has_classes? [klass]
54
+ end
55
+
56
+ #
57
+ # Checks if this DOM element has a set of given CSS classes
58
+ #
59
+ # @return true if the element has all teh given classes, otherwise false is returned
60
+ #
61
+ def has_classes?(klasses)
62
+ klasses1 = klasses.kind_of?(Array) ? klasses : klasses.split
63
+ klasses2 = classes.split
64
+ for k in klasses1 do
65
+ if not klasses2.find_index(k)
66
+ return false
67
+ end
68
+ end
69
+ return true
70
+ end
71
+
72
+ #
73
+ # Returns the raw HTML of this element as a string
74
+ #
75
+ def html()
76
+ return @driver.get_sc_core_query_element_html(@handle, @index)
77
+ end
78
+
79
+ #
80
+ # Returns the text of this element
81
+ #
82
+ def text()
83
+ return @driver.get_sc_core_query_element_text(@handle, @index)
84
+ end
85
+
86
+ #
87
+ # Returns the HTML tag of this element (e.g. IMG, A, DIV)
88
+ #
89
+ def tag()
90
+ return @driver.get_sc_core_query_element_tag(@handle, @index)
91
+ end
92
+
93
+ #
94
+ # Used to get the value of specific attribute belonging to the element
95
+ #
96
+ # @param val {String} the name of the attribute on the element
97
+ #
98
+ def attribute(val)
99
+ return @driver.get_sc_core_query_element_attribute(@handle, @index, val)
100
+ end
101
+
102
+ #
103
+ # If the method can not be found then assume we are trying to get the value
104
+ # of an attribute on the element.
105
+ #
106
+ def method_missing(sym, *args, &block)
107
+ return attribute(sym.to_s) if not sym.to_s =~ /\?$/
108
+ super
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,31 @@
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 ArgumentInvalidTypeError < Exception
10
+
11
+ def initialize(arg_name, value, *expected_types)
12
+
13
+ raise ArgumentError.new "invalid argument name supplied: #{arg_name}" if arg_name.nil?
14
+
15
+ message = "argument '#{arg_name}' is an invalid type: #{value} (#{value.class})."
16
+
17
+ if not expected_types.nil?
18
+ message << " Accepted types: "
19
+ expected_types.each do |type|
20
+ message << type.to_s << ", "
21
+ end
22
+ end
23
+
24
+ super(message)
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,30 @@
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 UnexpectedTypeError < Exception
10
+
11
+ def initialize(path, expected_type, result_type, value)
12
+
13
+ if value.kind_of?(Lebowski::Foundation::SCObject)
14
+ value = value.sc_class
15
+ end
16
+
17
+ if expected_type.kind_of?(Class) and expected_type.ancestors.member?(Lebowski::Foundation::SCObject)
18
+ expected_type = expected_type.represented_sc_class
19
+ end
20
+
21
+ message = "Did not get expected type '#{expected_type}' for path '#{path}'. Instead got #{result_type}: #{value}"
22
+
23
+ super(message)
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,87 @@
1
+ module Lebowski
2
+ module Foundation
3
+ module Mixins
4
+
5
+ #
6
+ # Mixin is used to provide colletion item view support to any view that
7
+ # that will be an item view for a collection view
8
+ #
9
+ module CollectionItemViewSupport
10
+
11
+ def has_collection_item_view_support()
12
+ return true
13
+ end
14
+
15
+ def index()
16
+ return @parent.item_views.index_of self
17
+ end
18
+
19
+ def next_item_view(offset=nil)
20
+ idx = @parent.item_views.index_of self
21
+ return nil if idx < 0
22
+ items_count = @parent.item_views.count
23
+ offset = offset.nil? ? 1 : offset
24
+ return nil if (idx + offset) >= items_count
25
+ return @parent.item_views[idx + offset]
26
+ end
27
+
28
+ def previous_item_view(offset=nil)
29
+ idx = @parent.item_views.index_of self
30
+ return nil if idx < 0
31
+ offset = offset.nil? ? 1 : offset
32
+ return nil if (idx - offset) < 0
33
+ return @parent.item_views[idx - offset]
34
+ end
35
+
36
+ def click()
37
+ self.scroll_to_visible
38
+ super
39
+ end
40
+
41
+ def selected?()
42
+ return self['isSelected']
43
+ end
44
+
45
+ def select()
46
+ self.click if (self['isSelected'] == false)
47
+ end
48
+
49
+ def select_add()
50
+ if self['isSelected'] == false
51
+ self.scroll_to_visible
52
+ self.key_down :meta_key
53
+ self.click
54
+ self.key_up :meta_key
55
+ end
56
+ end
57
+
58
+ def deselect()
59
+ if self['isSelected'] == true
60
+ self.scroll_to_visible
61
+ self.key_down :meta_key
62
+ self.click
63
+ self.key_up :meta_key
64
+ end
65
+ end
66
+
67
+ def can_drag_before?()
68
+ return false
69
+ end
70
+
71
+ def can_drag_after?()
72
+ return false
73
+ end
74
+
75
+ def apply_drag_before(source)
76
+ # no-op
77
+ end
78
+
79
+ def apply_drag_after(source)
80
+ # no-op
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,22 @@
1
+ module Lebowski
2
+ module Foundation
3
+ module Mixins
4
+
5
+ module DelegateSupport
6
+
7
+ def get_delegate_property(key, *delegates)
8
+ val = self[key]
9
+ return val if (not val.nil?)
10
+ return nil if (delegates.length == 0)
11
+ delegates.each do |del|
12
+ val = self["#{del}.#{key}"]
13
+ return val if (val != :undefined and not val.nil?)
14
+ end
15
+ return nil
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ module Lebowski
2
+ module Foundation
3
+
4
+ module Mixins
5
+
6
+ class InlineTextFieldError < Exception
7
+
8
+ end
9
+
10
+ #
11
+ # Mixin adds support for any view that makes use of the inline text field view
12
+ # (SC.InlineTextFieldView)
13
+ #
14
+ module InlineTextFieldSupport
15
+
16
+ def edit_inline_text_field(value)
17
+ pane = self['pane', 'SC.Pane']
18
+ inline_text_field = pane.child_views.find_first('SC.InlineTextFieldView')
19
+ if inline_text_field.nil?
20
+ raise InlineTextFieldError.new "Was unable to locate the inline text field view to edit"
21
+ end
22
+ inline_text_field.type value
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ module Lebowski
2
+ module Foundation
3
+ module Mixins
4
+
5
+ module KeyCheck
6
+
7
+ #
8
+ # Check if a key is pressed down. Note that the key is not specific to any object. So the
9
+ # following scenario is valid:
10
+ #
11
+ # objA.key_down? 'a' # => false
12
+ # objB.key_down 'a'
13
+ # objA.key_down? 'a' # => true
14
+ #
15
+ def key_down?(key)
16
+ return @driver.key_down? key
17
+ end
18
+
19
+ #
20
+ # Check if a key is pressed down. Note that the key is not specific to any object. So the
21
+ # following scenario is valid:
22
+ #
23
+ # objA.key_up? 'a' # => true
24
+ # objB.key_down 'a'
25
+ # objA.key_up? 'a' # => false
26
+ #
27
+ def key_up?(key)
28
+ return @driver.key_up? key
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,36 @@
1
+ module Lebowski
2
+ module Foundation
3
+ module Mixins
4
+
5
+ #
6
+ # Mixin provides support to any view that will act as a list item view
7
+ # for a list view.
8
+ #
9
+ module ListItemViewSupport
10
+ include CollectionItemViewSupport
11
+
12
+ def can_drag_before?()
13
+ return true
14
+ end
15
+
16
+ def can_drag_after?()
17
+ return true
18
+ end
19
+
20
+ def apply_drag_before(source)
21
+ source.drag_to self
22
+ end
23
+
24
+ def apply_drag_after(source)
25
+ source.drag_to self, 0, row_height
26
+ end
27
+
28
+ def row_height()
29
+ return @parent["rowHeightForContentIndex.#{index}"]
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ module Lebowski
2
+ module Foundation
3
+ module Mixins
4
+
5
+ module PositionedElement
6
+
7
+ def position()
8
+ return Coords.new(0,0)
9
+ end
10
+
11
+ def scroll_to_visible()
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,79 @@
1
+ module Lebowski
2
+ module Foundation
3
+ module Mixins
4
+
5
+ #
6
+ # Mixin provides support to objects that need to stall an
7
+ # action. This is needed in many cases where a user action is
8
+ # being performed. If an action is performed to quickly then
9
+ # SproutCore may not respond correctly and therefore cause
10
+ # unexpected behavior in the application
11
+ #
12
+ module StallSupport
13
+
14
+ DEFAULT_STALL = 0.2
15
+
16
+ DEFAULT_KEY_STALLS = {
17
+ :click => 0.2,
18
+ :double_click => 0.5,
19
+ :select => 0.5
20
+ }
21
+
22
+ @@adjusted_default_stall = DEFAULT_STALL
23
+
24
+ @@adjusted_default_key_stalls = {}
25
+
26
+ def self.adjust_all_stalls(stall)
27
+ return if stall.nil? or stall <= 0
28
+ @@adjusted_default_stall = stall
29
+ DEFAULT_KEY_STALLS.each_key do |key|
30
+ @@adjusted_default_key_stalls[key] = stall
31
+ end
32
+ end
33
+
34
+ def self.adjust_default_stall(stall)
35
+ return if stall.nil? or stall <= 0
36
+ @@adjusted_default_stall = stall
37
+ end
38
+
39
+ def self.adjust_default_key_stall(key, stall)
40
+ return if stall.nil? or stall <= 0
41
+ @@adjusted_default_key_stalls[key] = stall
42
+ end
43
+
44
+ def self.reset()
45
+ @@adjusted_default_stall = DEFAULT_STALL
46
+ @@adjusted_default_key_stalls.clear
47
+ end
48
+
49
+ def stall(key, stall=nil)
50
+ if stall.nil?
51
+ sleep StallSupport.default_key_stall(key)
52
+ elsif stall <= 0
53
+ sleep StallSupport.default_stall
54
+ else
55
+ sleep stall
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def self.default_stall()
62
+ return @@adjusted_default_stall
63
+ end
64
+
65
+ def self.default_key_stall(key)
66
+ value = @@adjusted_default_key_stalls[key]
67
+ if value.nil?
68
+ value = DEFAULT_KEY_STALLS[key]
69
+ return default_stall if value.nil?
70
+ return value
71
+ end
72
+ return value
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+ end
79
+ end