pincers 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pincers/backend/nokogiri.rb +9 -2
- data/lib/pincers/backend/webdriver.rb +15 -14
- data/lib/pincers/core/search_context.rb +42 -12
- data/lib/pincers/errors.rb +15 -7
- data/lib/pincers/extension/actions.rb +4 -0
- data/lib/pincers/extension/queries.rb +5 -1
- data/lib/pincers/factories/base.rb +0 -2
- data/lib/pincers/version.rb +1 -1
- data/lib/pincers.rb +1 -0
- metadata +27 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90b1470b17e772e804f87e809335d6b6f6bbc705
|
4
|
+
data.tar.gz: 8604135f3c47aba37b6426905eb90974cd683494
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b89aac01d30859041bf708e6ddac7f4207d8ea70541a9925806193f7b84dab9048b222013205d54558af4a87810f459599c43476b65a42b66809de55539741b0
|
7
|
+
data.tar.gz: 89f2ca14a776b9aba4c60f51b19a594d9b7a1c59705ebd260cb6aeb30bd5690af4571ae3444e6e076a4770d03bddf4964139d2ac311f7d4d63e125e4b5f88430
|
@@ -5,6 +5,8 @@ module Pincers::Backend
|
|
5
5
|
|
6
6
|
class Nokogiri < Base
|
7
7
|
|
8
|
+
BOOL_PROPERTIES = [:selected, :disabled, :checked, :required]
|
9
|
+
|
8
10
|
def document_root
|
9
11
|
[document]
|
10
12
|
end
|
@@ -41,9 +43,14 @@ module Pincers::Backend
|
|
41
43
|
|
42
44
|
def extract_element_attribute(_element, _name)
|
43
45
|
_name = _name.to_sym
|
44
|
-
|
45
46
|
value = _element[_name]
|
46
|
-
|
47
|
+
|
48
|
+
if BOOL_PROPERTIES.include? _name
|
49
|
+
value = !value.nil?
|
50
|
+
elsif _name == :value
|
51
|
+
value = checkbox_value_fix _element, value
|
52
|
+
end
|
53
|
+
|
47
54
|
value
|
48
55
|
end
|
49
56
|
|
@@ -5,6 +5,8 @@ module Pincers::Backend
|
|
5
5
|
|
6
6
|
class Webdriver < Base
|
7
7
|
|
8
|
+
DOM_PROPERTIES = [:selected, :disabled, :checked, :value, :required]
|
9
|
+
|
8
10
|
alias :driver :document
|
9
11
|
|
10
12
|
def initialize(_driver)
|
@@ -76,11 +78,22 @@ module Pincers::Backend
|
|
76
78
|
|
77
79
|
def extract_element_attribute(_element, _name)
|
78
80
|
_element = ensure_element _element
|
79
|
-
|
81
|
+
if DOM_PROPERTIES.include? _name.to_sym
|
82
|
+
driver.execute_script("return arguments[0]['#{_name}'];", _element)
|
83
|
+
else
|
84
|
+
_element[_name]
|
85
|
+
end
|
80
86
|
end
|
81
87
|
|
82
88
|
def set_element_attribute(_element, _name, _value)
|
83
|
-
|
89
|
+
_element = ensure_element _element
|
90
|
+
if DOM_PROPERTIES.include? _name.to_sym
|
91
|
+
driver.execute_script("arguments[0]['#{_name}'] = #{_value.to_json};", _element)
|
92
|
+
elsif _value == ''
|
93
|
+
driver.execute_script("arguments[0].removeAttribute('#{_name}')", _element)
|
94
|
+
else
|
95
|
+
driver.execute_script("arguments[0].setAttribute('#{_name}', #{_value.to_json})", _element)
|
96
|
+
end
|
84
97
|
end
|
85
98
|
|
86
99
|
def element_is_actionable?(_element)
|
@@ -136,18 +149,6 @@ module Pincers::Backend
|
|
136
149
|
driver.switch_to.default_content
|
137
150
|
end
|
138
151
|
|
139
|
-
def check_visible(_elements)
|
140
|
-
_elements.first.displayed?
|
141
|
-
end
|
142
|
-
|
143
|
-
def check_enabled(_elements)
|
144
|
-
check_visible(_elements) and _elements.first.enabled?
|
145
|
-
end
|
146
|
-
|
147
|
-
def check_not_visible(_elements)
|
148
|
-
not _elements.any? { |e| e.displayed? }
|
149
|
-
end
|
150
|
-
|
151
152
|
private
|
152
153
|
|
153
154
|
def search(_element, _query, _limit)
|
@@ -20,6 +20,7 @@ module Pincers::Core
|
|
20
20
|
@scope = if @elements.nil? then nil else :all end
|
21
21
|
@parent = _parent
|
22
22
|
@query = _query
|
23
|
+
@waiting = false
|
23
24
|
end
|
24
25
|
|
25
26
|
def frozen?
|
@@ -49,8 +50,8 @@ module Pincers::Core
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def element!
|
52
|
-
wait(:present)
|
53
|
-
raise Pincers::EmptySetError.new self if
|
53
|
+
wait(:present) if should_wait?
|
54
|
+
raise Pincers::EmptySetError.new self if element.nil?
|
54
55
|
element
|
55
56
|
end
|
56
57
|
|
@@ -78,7 +79,7 @@ module Pincers::Core
|
|
78
79
|
end
|
79
80
|
|
80
81
|
def first
|
81
|
-
wait?(:present)
|
82
|
+
wait?(:present) if should_wait?
|
82
83
|
if element.nil? then nil else wrap_siblings [element] end
|
83
84
|
end
|
84
85
|
|
@@ -174,28 +175,46 @@ module Pincers::Core
|
|
174
175
|
|
175
176
|
# waiting
|
176
177
|
|
177
|
-
def wait?(_condition, _options={}, &_block)
|
178
|
-
|
178
|
+
def wait?(_condition=nil, _options={}, &_block)
|
179
|
+
|
180
|
+
if _condition.is_a? Hash
|
181
|
+
_options = _condition
|
182
|
+
_condition = nil
|
183
|
+
end
|
184
|
+
|
185
|
+
poll_until(_options) do
|
186
|
+
next ensure_block _block if _block
|
187
|
+
|
179
188
|
case _condition
|
180
189
|
when :present
|
181
190
|
ensure_present
|
182
191
|
when :actionable
|
183
192
|
ensure_present and ensure_actionable
|
193
|
+
when :enabled
|
194
|
+
ensure_present and !attribute(:disabled)
|
184
195
|
else
|
185
|
-
|
186
|
-
raise Pincers::MissingFeatureError.new check_method unless backend.respond_to? check_method
|
187
|
-
ensure_present and check_method.call(elements)
|
196
|
+
ensure_present and !!attribute(_condition)
|
188
197
|
end
|
189
198
|
end
|
190
199
|
end
|
191
200
|
|
192
|
-
def wait(_condition, _options={})
|
193
|
-
|
201
|
+
def wait(_condition=nil, _options={}, &_block)
|
202
|
+
|
203
|
+
if _condition.is_a? Hash
|
204
|
+
_options = _condition
|
205
|
+
_condition = nil
|
206
|
+
end
|
207
|
+
|
208
|
+
raise Pincers::ConditionTimeoutError.new(self, _condition) unless wait?(_condition, _options, &_block)
|
194
209
|
return self
|
195
210
|
end
|
196
211
|
|
197
212
|
private
|
198
213
|
|
214
|
+
def should_wait?
|
215
|
+
!frozen? && !advanced_mode? && !@waiting
|
216
|
+
end
|
217
|
+
|
199
218
|
def advanced_mode?
|
200
219
|
root.advanced_mode?
|
201
220
|
end
|
@@ -209,6 +228,17 @@ module Pincers::Core
|
|
209
228
|
backend.element_is_actionable? element
|
210
229
|
end
|
211
230
|
|
231
|
+
def ensure_block(_block)
|
232
|
+
begin
|
233
|
+
@waiting = true
|
234
|
+
_block.call(self) != false
|
235
|
+
rescue Pincers::NavigationError
|
236
|
+
return false
|
237
|
+
ensure
|
238
|
+
@waiting = false
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
212
242
|
def wrap_errors
|
213
243
|
begin
|
214
244
|
yield
|
@@ -221,7 +251,7 @@ module Pincers::Core
|
|
221
251
|
|
222
252
|
def perform_action
|
223
253
|
wrap_errors do
|
224
|
-
wait(:actionable)
|
254
|
+
wait(:actionable) if should_wait?
|
225
255
|
yield elements.first
|
226
256
|
end
|
227
257
|
self
|
@@ -258,7 +288,7 @@ module Pincers::Core
|
|
258
288
|
end
|
259
289
|
end
|
260
290
|
|
261
|
-
def poll_until(
|
291
|
+
def poll_until(_options={})
|
262
292
|
timeout = _options.fetch :timeout, root.default_timeout
|
263
293
|
interval = _options.fetch :interval, root.default_interval
|
264
294
|
end_time = Time.now + timeout
|
data/lib/pincers/errors.rb
CHANGED
@@ -34,23 +34,31 @@ module Pincers
|
|
34
34
|
|
35
35
|
end
|
36
36
|
|
37
|
-
class
|
37
|
+
class NavigationError < ContextError; end
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
class ConditionTimeoutError < NavigationError
|
40
|
+
|
41
|
+
def initialize(_context, _condition)
|
42
|
+
message = if _condition
|
43
|
+
"Timed out waiting element to be #{_condition}"
|
44
|
+
else
|
45
|
+
"Timed out waiting for element match custom condition"
|
46
|
+
end
|
47
|
+
|
48
|
+
super _context, message
|
41
49
|
end
|
42
50
|
|
43
51
|
end
|
44
52
|
|
45
|
-
class
|
53
|
+
class EmptySetError < NavigationError
|
46
54
|
|
47
|
-
def initialize(_context
|
48
|
-
super _context, "
|
55
|
+
def initialize(_context)
|
56
|
+
super _context, "This set is empty"
|
49
57
|
end
|
50
58
|
|
51
59
|
end
|
52
60
|
|
53
|
-
class BackendError <
|
61
|
+
class BackendError < NavigationError
|
54
62
|
|
55
63
|
attr_reader :document
|
56
64
|
attr_reader :original
|
@@ -10,12 +10,16 @@ module Pincers::Extension
|
|
10
10
|
|
11
11
|
case input_mode
|
12
12
|
when :text
|
13
|
+
wait :enabled
|
13
14
|
set_text _value.to_s
|
14
15
|
when :select
|
16
|
+
wait :enabled
|
15
17
|
return set_selected _value, _options
|
16
18
|
when :checkbox, :radio
|
19
|
+
wait :enabled
|
17
20
|
return set_checked _value
|
18
21
|
when :button
|
22
|
+
wait :enabled
|
19
23
|
click if _value
|
20
24
|
else
|
21
25
|
return false
|
@@ -16,6 +16,10 @@ module Pincers::Extension
|
|
16
16
|
xpath builder.expression, query_options
|
17
17
|
end
|
18
18
|
|
19
|
+
def id
|
20
|
+
self[:id]
|
21
|
+
end
|
22
|
+
|
19
23
|
def value
|
20
24
|
case input_mode
|
21
25
|
when :checkbox, :radio
|
@@ -27,7 +31,7 @@ module Pincers::Extension
|
|
27
31
|
|
28
32
|
[:selected, :checked, :disabled, :required].each do |attr_name|
|
29
33
|
define_method "#{attr_name}?" do
|
30
|
-
|
34
|
+
self[attr_name]
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
data/lib/pincers/version.rb
CHANGED
data/lib/pincers.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pincers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ignacio Baixas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.6
|
19
|
+
version: '1.6'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.6
|
26
|
+
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: selenium-webdriver
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,70 +56,70 @@ dependencies:
|
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ~>
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec-nc
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ~>
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: guard
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: guard-rspec
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ~>
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
@@ -128,85 +128,85 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 1.6
|
131
|
+
version: '1.6'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ~>
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 1.6
|
138
|
+
version: '1.6'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: pry
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ~>
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ~>
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: pry-remote
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- -
|
157
|
+
- - ~>
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '0'
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- -
|
164
|
+
- - ~>
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: pry-nav
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- -
|
171
|
+
- - ~>
|
172
172
|
- !ruby/object:Gem::Version
|
173
173
|
version: '0'
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
|
-
- -
|
178
|
+
- - ~>
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: rack
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
184
184
|
requirements:
|
185
|
-
- -
|
185
|
+
- - ~>
|
186
186
|
- !ruby/object:Gem::Version
|
187
187
|
version: '0'
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
|
-
- -
|
192
|
+
- - ~>
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: thin
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
198
198
|
requirements:
|
199
|
-
- -
|
199
|
+
- - ~>
|
200
200
|
- !ruby/object:Gem::Version
|
201
201
|
version: '0'
|
202
202
|
type: :development
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
|
-
- -
|
206
|
+
- - ~>
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
|
-
description:
|
209
|
+
description: Web automation DSL on top of webdriver and nokogiri
|
210
210
|
email:
|
211
211
|
- ignacio@platan.us
|
212
212
|
executables: []
|