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 +4 -4
- data/lib/domkey/exception.rb +4 -0
- data/lib/domkey/version.rb +1 -1
- data/lib/domkey/view.rb +1 -0
- data/lib/domkey/view/checkbox_group.rb +12 -63
- data/lib/domkey/view/label_mapper.rb +7 -1
- data/lib/domkey/view/labeled_group.rb +22 -11
- data/lib/domkey/view/option_selectable.rb +102 -0
- data/lib/domkey/view/option_selectable_group.rb +120 -0
- data/lib/domkey/view/page_object.rb +11 -11
- data/lib/domkey/view/page_object_collection.rb +1 -1
- data/lib/domkey/view/radio_group.rb +9 -58
- data/lib/domkey/view/select_list.rb +67 -0
- data/lib/domkey/view/widgetry/dispatcher.rb +51 -0
- data/lib/domkey/view/widgetry/package.rb +49 -0
- data/spec/checkbox_group_spec.rb +81 -5
- data/spec/option_selectable_spec.rb +57 -0
- data/spec/radio_group_spec.rb +62 -4
- data/spec/select_list_spec.rb +212 -0
- metadata +11 -6
- data/lib/domkey/view/watir_widget.rb +0 -106
- data/lib/domkey/view/widgetry_package.rb +0 -48
- data/spec/watir_widget_select_spec.rb +0 -176
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0468e0993e03c228863792b2979fc0518aea17db
|
4
|
+
data.tar.gz: d36475ac117f17891905d01328dadca7bc08fe90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef11d67c2261cc2e7f4228bbe1f2466a1d82f4ebb8eedd895850c9e48d109080506ae91f6a40055184308e04f24395aedc5c81d0f48d5d7ba866d23b78a4e45d
|
7
|
+
data.tar.gz: 5b613799843aedb4959c422fe4dfcf91c28740903c78e4e86dc4b40e971ff803a77567df785e066ae702069bcc5becdb56246c98a7feba1012bc0e96b8cf49e4
|
data/lib/domkey/exception.rb
CHANGED
data/lib/domkey/version.rb
CHANGED
data/lib/domkey/view.rb
CHANGED
@@ -1,74 +1,23 @@
|
|
1
|
-
require 'domkey/view/
|
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
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
|
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
|
-
#
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
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/
|
2
|
-
require 'domkey/view/
|
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
|
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
|
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
|
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
|
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
|
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 [
|
85
|
-
def
|
86
|
-
|
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
|
99
|
+
rescue StandardError
|
100
100
|
return package #suitecase exploded, proc returned
|
101
101
|
end
|
102
102
|
if peeked_inside.respond_to?(:each_pair) # hash
|