domkey 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 45e6ac05a48d93eede629f82f2a5b04b14037f62
4
- data.tar.gz: 9c3b5d281b8b000852489e1933de6b855b2975e3
3
+ metadata.gz: 0468e0993e03c228863792b2979fc0518aea17db
4
+ data.tar.gz: d36475ac117f17891905d01328dadca7bc08fe90
5
5
  SHA512:
6
- metadata.gz: aa5af099b7354c11538d238e9c4a59eb91cf41a7f7845fe10bd92659af309e7e65ebf1630d722952e17a39ca1a0e9a790e955a00d91df35a074ea9de9b83d3d1
7
- data.tar.gz: 2fe75c7ca69ba9f0656491cea2a358a048f815b5da77bc7d614425c4a4a5a353b653364b4f13b522e2a366de699744389e3244dcde80822a7ed9fd6ab727fe56
6
+ metadata.gz: ef11d67c2261cc2e7f4228bbe1f2466a1d82f4ebb8eedd895850c9e48d109080506ae91f6a40055184308e04f24395aedc5c81d0f48d5d7ba866d23b78a4e45d
7
+ data.tar.gz: 5b613799843aedb4959c422fe4dfcf91c28740903c78e4e86dc4b40e971ff803a77567df785e066ae702069bcc5becdb56246c98a7feba1012bc0e96b8cf49e4
@@ -2,5 +2,9 @@ module Domkey
2
2
  module Exception
3
3
  class Error < StandardError
4
4
  end
5
+ class NotImplementedError < Error
6
+ end
7
+ class NotFoundError < Error
8
+ end
5
9
  end
6
10
  end
@@ -1,3 +1,3 @@
1
1
  module Domkey
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -2,6 +2,7 @@ require 'domkey/view/page_object'
2
2
  require 'domkey/view/page_object_collection'
3
3
  require 'domkey/view/radio_group'
4
4
  require 'domkey/view/checkbox_group'
5
+ require 'domkey/view/select_list'
5
6
  require 'domkey/view/cargo'
6
7
 
7
8
  module Domkey
@@ -1,74 +1,23 @@
1
- require 'domkey/view/labeled_group'
1
+ require 'domkey/view/option_selectable_group'
2
+
2
3
  module Domkey
3
4
 
4
5
  module View
5
6
 
6
- # Acts like OptionSelectable object
7
7
  # CheckboxGroup allows you to interact with PageObjectCollection of checkboxes as a single PageObject.
8
- # Checkboxes collection is constrained by the same name attribute and acts like on object.
9
- # It behaves like a Multi Select list.
10
- # It can none, one or more options selected
11
- class CheckboxGroup < PageObjectCollection
12
-
13
- # clears all options and sets only the desired value(s)
14
- # @param [String, Regexp] find value attribute or match value and set that checkbox
15
- # @param [Array<String, Regexp>] find each value attribute and set each checkbox
16
- # @param [False] uncheck any checked checkboxes
17
- def set value
18
- validate_scope
19
- element.each { |e| e.clear }
20
- return unless value
21
- [*value].each do |v|
22
- e = case v
23
- when String
24
- element.find { |e| e.value == v }
25
- when Regexp
26
- element.find { |e| e.value.match(v) }
27
- end
28
- e ? e.set : fail(Exception::Error, "Checkbox to be set not found by value: #{v.inspect}")
29
- end
30
- end
31
-
32
- # @return [Array<String>] value attributes of each checked checkbox
33
- def value
34
- validate_scope
35
- element.find_all { |e| e.set? }.map { |e| e.value }
36
- end
37
-
38
- def options
39
- validate_scope
40
- element.map { |e| e.value }
41
- end
42
-
43
- # convert to LabeledGroup settable by corresponding label text
44
- def to_labeled
45
- LabeledGroup.new(self)
46
- end
47
-
48
- # @yield [PageObject]
49
- def each(&blk)
50
- validate_scope
51
- super(&blk)
52
- end
53
-
54
- # @return [Array<PageObject>]
55
- def to_a
56
- validate_scope
57
- super
58
- end
8
+ # Acts like OptionSelectable
9
+ # Checkboxes collection is constrained by the same name attribute
10
+ # Behaves like a multi Select list.
11
+ # It can have none, one or more options selected
12
+ class CheckboxGroup < OptionSelectableGroup
59
13
 
60
14
  private
61
15
 
62
- # precondition on acting on this collection
63
- # @return [true] when all checkboxes in collection share the same name attribute
64
- # @raise [Exception::Error] when where is more than one unique name attribute
65
- # --
66
- # returns true on subsequent unless magically more radios show up after initial validation
67
- def validate_scope
68
- return if @validated
69
- groups = element.map { |e| e.name }.uniq
70
- fail(Exception::Error, "CheckboxGroup definition scope too broad: Found #{groups.count} checkbox groups with names: #{groups}") unless (groups.size == 1)
71
- @validated = true
16
+ # @api private
17
+ # unselects all checkboxes before setting it with desired value
18
+ def before_set
19
+ validate_scope
20
+ each { |o| o.set false }
72
21
  end
73
22
  end
74
23
  end
@@ -2,8 +2,9 @@ module Domkey
2
2
 
3
3
  module View
4
4
 
5
- # return collection of PageObjects for label locators corresponding to id of each element in a collection
6
5
  class LabelMapper
6
+
7
+ # return collection of PageObjects for label locators corresponding to id of each element in a collection
7
8
  # @param [Array<PageObject>]
8
9
  # @param [PageObjectCollection]
9
10
  # @return [Array<PageObject>] where each PageObject is a locator for label for an id of a PageObject passed in parameters
@@ -12,6 +13,11 @@ module Domkey
12
13
  PageObject.new -> { label(for: e.element.id) }, e.container
13
14
  end
14
15
  end
16
+
17
+ # provide PageObject wrapping label corresponding to id of element in pageobject.
18
+ def self.find pageobject
19
+ PageObject.new -> { label(for: pageobject.element.id) }, pageobject.container
20
+ end
15
21
  end
16
22
  end
17
23
  end
@@ -16,10 +16,31 @@ module Domkey
16
16
  __setobj__(group)
17
17
  end
18
18
 
19
+ def before_set
20
+ __getobj__.set false
21
+ end
22
+
19
23
  # @param value [String] a label text to set a corresponding element referenced
20
24
  # @param value [Array<String>] one or more labels
21
25
  def set value
22
- __getobj__.set false
26
+ before_set
27
+ set_strategy(value)
28
+ end
29
+
30
+ # @return [Array<String>] label texts for selected elements
31
+ def value
32
+ selected_ones = __getobj__.find_all { |e| e.element.set? }
33
+ LabelMapper.for(selected_ones).map { |e| e.element.text }
34
+ end
35
+
36
+ # @return [Array<String>] label texts for all elements in a group
37
+ def options
38
+ LabelMapper.for(__getobj__).map { |e| e.element.text }
39
+ end
40
+
41
+ private
42
+
43
+ def set_strategy value
23
44
  labels = self.options
24
45
  indices = [*value].map do |what|
25
46
  i = case what
@@ -35,16 +56,6 @@ module Domkey
35
56
  end
36
57
  end
37
58
 
38
- # @return [Array<String>] label texts for selected elements
39
- def value
40
- selected_ones = __getobj__.find_all { |e| e.element.set? }
41
- LabelMapper.for(selected_ones).map { |e| e.element.text }
42
- end
43
-
44
- # @return [Array<String>] label texts for all elements in a group
45
- def options
46
- LabelMapper.for(__getobj__).map { |e| e.element.text }
47
- end
48
59
  end
49
60
  end
50
61
  end
@@ -0,0 +1,102 @@
1
+ module Domkey
2
+ module View
3
+ module OptionSelectable
4
+
5
+ # clears all options and sets only the desired value(s)
6
+ # @param [String, Regexp] sets default designated option by String or Regexp
7
+ # @param [Array<String, Regexp>] sets each String, Regexp
8
+ # @param [False] unselects all options
9
+ # @param [Hash{how => value}] selects by how strategy where how is a symbol :label, :index, :text, :value
10
+ # Clients need to implement individual strategy for each 'how' => 'value' pair based on what it means to be selected by what
11
+ def set value
12
+ before_set
13
+ set_strategy value
14
+ end
15
+
16
+ # @param [] opts. Represents a qualifier of what types of options to return. defaults to empty
17
+ # @return [Array<String>] when opts param emtpy returns array of default strings implemented by client
18
+ # @param [Symbol,Array<Symbol>] symbols represents what option selector to return
19
+ # @return [Array<Hash{what => value}] where what is a symbol for option selector, :index, :value, :text, :label
20
+ def value *opts
21
+ opts = opts.flatten
22
+ return value_by_default if (opts.empty? || opts.find { |e| e.kind_of?(String) })
23
+ value_by_options opts
24
+ end
25
+
26
+ # similar strategy to value but returns all options and not only selected ones
27
+ def options *opts
28
+ opts = opts.flatten
29
+ return options_by_default if opts.empty?
30
+ options_by opts
31
+ end
32
+
33
+ private
34
+
35
+ def options_by_default
36
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
37
+ end
38
+
39
+ def options_by opts
40
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
41
+ end
42
+
43
+ def value_by_default
44
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
45
+ end
46
+
47
+ def value_by_options options
48
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
49
+ end
50
+
51
+ def before_set
52
+ # hook. client can provide actions to be taken before setting this PageObject
53
+ end
54
+
55
+ # strategy for selecting OptionSelectable object
56
+ def set_strategy value
57
+ case value
58
+ when String
59
+ set_by_string(value)
60
+ when Regexp
61
+ set_by_regexp(value)
62
+ when Array
63
+ value.each { |v| set_strategy(v) }
64
+ when Hash
65
+ value.each_pair do |how, value|
66
+ case how
67
+ when :label
68
+ set_by_label(value)
69
+ when :text
70
+ set_strategy(value)
71
+ when :index
72
+ set_by_index(value)
73
+ when :value
74
+ set_by_value(value)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def set_by_string value
81
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
82
+ end
83
+
84
+ def set_by_regexp value
85
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
86
+ end
87
+
88
+ def set_by_label value
89
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
90
+ end
91
+
92
+ def set_by_index value
93
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
94
+ end
95
+
96
+ def set_by_value value
97
+ fail Exception::NotImplementedError, "Subclass responsible for implementing"
98
+ end
99
+
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,120 @@
1
+ require 'domkey/view/option_selectable'
2
+ require 'domkey/view/labeled_group'
3
+
4
+ module Domkey
5
+ module View
6
+
7
+ #OptionsSelectable CheckboxGroup, RadioGroup
8
+ class OptionSelectableGroup < PageObjectCollection
9
+
10
+ include OptionSelectable
11
+
12
+ def set_by_index value
13
+ [*value].each do |i|
14
+ self[i.to_i].set(true)
15
+ end
16
+ end
17
+
18
+ def set_by_label value
19
+ to_labeled.__send__(:set_strategy, value)
20
+ end
21
+
22
+ def set_by_regexp value
23
+ o = find { |o| o.value.match(value) }
24
+ o ? o.element.set : fail(Exception::NotFoundError, "Element not found with value: #{v.inspect}")
25
+ end
26
+
27
+ def set_by_string value
28
+ o = find { |o| o.value == value }
29
+ o ? o.element.set : fail(Exception::NotFoundError, "Element not found with value: #{v.inspect}")
30
+ end
31
+
32
+
33
+ def value_by_default
34
+ validate_scope
35
+ find_all { |e| e.element.set? }.map { |e| e.value }
36
+ end
37
+
38
+ def value_by_options opts
39
+ validate_scope
40
+ result = []
41
+ each_with_index do |e, i|
42
+ if e.element.set?
43
+
44
+ v = opts.map do |o|
45
+ case o
46
+ when :index
47
+ [o, i]
48
+ when :label, :text
49
+ [o, LabelMapper.find(e).element.text]
50
+ else
51
+ [o, e.send(o)]
52
+ end
53
+ end
54
+ result << Hash[v]
55
+ end
56
+ end
57
+ result
58
+ end
59
+
60
+ def options_by_default
61
+ validate_scope
62
+ map { |e| e.value }
63
+ end
64
+
65
+ def options_by opts
66
+ validate_scope
67
+ result = []
68
+ each_with_index do |e, i|
69
+
70
+ v = opts.map do |o|
71
+ case o
72
+ when :index
73
+ [o, i]
74
+ when :label, :text
75
+ [o, LabelMapper.find(e).element.text]
76
+ else
77
+ [o, e.send(o)]
78
+ end
79
+ end
80
+ result << Hash[v]
81
+ end
82
+
83
+ result
84
+ end
85
+
86
+ # convert to LabeledGroup settable by corresponding label text
87
+ def to_labeled
88
+ LabeledGroup.new(self)
89
+ end
90
+
91
+
92
+ # @yield [PageObject]
93
+ def each(&blk)
94
+ validate_scope
95
+ super(&blk)
96
+ end
97
+
98
+ # @return [Array<PageObject>]
99
+ def to_a
100
+ validate_scope
101
+ super
102
+ end
103
+
104
+ private
105
+
106
+ # precondition on acting on this collection
107
+ # @return [true] when all radios in collection share the same name attribute
108
+ # @raise [Exception::Error] when where is more than one unique name attribute
109
+ # --
110
+ # returns true on subsequent unless magically more radios show up after initial validation
111
+ def validate_scope
112
+ return if @validated
113
+ groups = element.map { |e| e.name }.uniq
114
+ fail(Exception::Error, "RadioGroup definition scope too broad: Found #{groups.count} radio groups with names: #{groups}") unless (groups.size == 1)
115
+ @validated = true
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -1,5 +1,5 @@
1
- require 'domkey/view/widgetry_package'
2
- require 'domkey/view/watir_widget'
1
+ require 'domkey/view/widgetry/package'
2
+ require 'domkey/view/widgetry/dispatcher'
3
3
 
4
4
  module Domkey
5
5
 
@@ -52,13 +52,13 @@ module Domkey
52
52
  class PageObject
53
53
 
54
54
  # @api private
55
- include WidgetryPackage
55
+ include Widgetry::Package
56
56
 
57
57
  # Each Semantic PageObject defines what value means for itself
58
58
  # @param [SemanticValue] Delegated to WebdriverElement and we expect it to respond to set
59
59
  # @parma [Hash{Symbol => SemanticValue}]
60
60
  def set value
61
- return watir_widget.set value unless value.respond_to?(:each_pair)
61
+ return widgetry_dispatcher.set value unless value.respond_to?(:each_pair)
62
62
  value.each_pair { |k, v| package.fetch(k).set(v) }
63
63
  end
64
64
 
@@ -68,22 +68,22 @@ module Domkey
68
68
  # @return [SemanticValue] delegated to WebdriverElement and we expect it to respond to value message
69
69
  # @return [Hash{Symbol => SemanticValue}]
70
70
  def value
71
- return watir_widget.value unless package.respond_to?(:each_pair)
71
+ return widgetry_dispatcher.value unless package.respond_to?(:each_pair)
72
72
  Hash[package.map { |key, pageobject| [key, pageobject.value] }]
73
73
  end
74
74
 
75
75
  def options
76
- return watir_widget.options unless package.respond_to?(:each_pair)
76
+ return widgetry_dispatcher.options unless package.respond_to?(:each_pair)
77
77
  Hash[package.map { |key, pageobject| [key, pageobject.options] }]
78
78
  end
79
79
 
80
80
  private
81
81
 
82
- # wrap instantiator with strategy for setting and getting value for watir object
82
+ # wrap instantiator with strategy for setting and getting value for underlying object
83
83
  # expects that element to respond to set and value
84
- # @returns [WatirWidget]
85
- def watir_widget
86
- WatirWidget.new(instantiator)
84
+ # @returns [Widgetry::Dispatcher] that responds to set, value, options
85
+ def widgetry_dispatcher
86
+ Widgetry.dispatcher(instantiator)
87
87
  end
88
88
 
89
89
  # @api private
@@ -96,7 +96,7 @@ module Domkey
96
96
  begin
97
97
  # peek inside suitcase that is proc. XXX ouch, ugly
98
98
  peeked_inside = package.call
99
- rescue NoMethodError
99
+ rescue StandardError
100
100
  return package #suitecase exploded, proc returned
101
101
  end
102
102
  if peeked_inside.respond_to?(:each_pair) # hash