ferrumwizard 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebfbe644929b142f88f8dc30e66db208bc8fa6c328eea266b18b6e6bf5c08da8
4
- data.tar.gz: f5e5403ad7dc857b0086213ef42e521fb91232fd93466036d22c35d269629804
3
+ metadata.gz: eb46fd03834d035f319b5654848eb8db05c4d8d870b59f261657fedc42b60222
4
+ data.tar.gz: a0e9d66110acbf0439494087795620675b10743eb767891e28cd9d0db55b4475
5
5
  SHA512:
6
- metadata.gz: 44ac0fdfca21e6b4bfdc42afe8bb7826de0b1df0c003b86bb19c025795633c9cad17962cd842762bb7c23c822757bd151a26dd11502015f7484f01e151d7f297
7
- data.tar.gz: 5ac3fd607f57b5b422b2e81b32ab29106bf80691ae445dcca405808fd087718d177006c790c73956521954e306ddc2fbea9597b1790cf5049027ccca9f201f11
6
+ metadata.gz: f7f3129f81ae7a79646f3ce13299a174265f7d42c1be53ef88dffe9461fddc42793c28b97ba55703d5ccfe62ef5aa5a9dd3a80665d3b3a897550de0d83325946
7
+ data.tar.gz: c7c5bac0cde40acc8d91a07e55890043bc16ae08d8533b4f0cf24719419cf62d5ee012b059dfd5d15befcd619140632cd4194dbb3294e09c1038f022ebccd524
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -8,96 +8,214 @@ require 'ferrum'
8
8
 
9
9
  class FerrumWizard
10
10
 
11
- attr_reader :browser, :links
11
+ attr_reader :browser, :links, :radio, :buttons, :js_methods
12
12
 
13
13
  def initialize(url, headless: true, debug: false)
14
14
 
15
15
  @url, @debug = url, debug
16
16
  @browser = Ferrum::Browser.new headless: headless
17
-
17
+ sleep 2
18
+ end
19
+
20
+ def inspect()
21
+ "#<FerrumWizard>"
18
22
  end
19
23
 
20
- def login(username, password)
24
+ def login(usernamex=nil, passwordx=nil, username: usernamex, password: passwordx)
25
+
26
+ puts 'username: ' + username.inspect if @debug
21
27
 
22
28
  b = @browser
23
29
  b.goto(@url)
24
-
30
+ @browser.network.wait_for_idle
31
+ sleep 3
25
32
 
26
33
  # search for the username input box
27
34
  e_username = b.at_xpath('//input[@type="email"]')
28
-
35
+ puts 'e_username: ' + e_username.inspect if @debug
36
+ sleep 1
29
37
  # search for the password input box
30
38
  e_password = b.at_xpath('//input[@type="password"]')
31
-
32
- if e_username and e_password then
33
-
34
- e_username.focus.type(username)
35
- e_password.focus.type(password, :Enter)
36
-
39
+ sleep 1
40
+
41
+ if username and e_username then
42
+ puts 'entering the username' if @debug
43
+ e_username.focus.type(username)
44
+ sleep 1
37
45
  end
38
46
 
47
+ e_password.focus.type(password, :Enter) if e_password
48
+ @browser.network.wait_for_idle
49
+
39
50
  sleep 4
40
- fetch_links()
41
- self
51
+
52
+ scan_page()
42
53
 
43
- end
54
+ end
44
55
 
45
56
  def quit
46
57
  @browser.quit
47
58
  end
59
+
60
+ def scan_page()
61
+
62
+ @doc = Rexle.new @browser.body
63
+ fetch_links()
64
+ scan_form_elements()
65
+ scan_js_links()
66
+ self
67
+ end
48
68
 
49
69
  def to_rb()
50
70
  end
51
71
 
52
72
  private
53
73
 
74
+ def fetch_buttons()
75
+
76
+ a2 = @browser.xpath('//input[@type="button"]')
77
+ @buttons = a2.flat_map do |x|
78
+
79
+ a = x.value.split(/\W+/).map {|label| [label, x]}
80
+ a << [x.value, x]
81
+ a + a.map {|x, obj| [x.downcase, obj]}
82
+
83
+ end.to_h
84
+
85
+ names = @buttons.keys.map(&:downcase).uniq.select {|x| x =~ /^\w+$/}
86
+ buttons = @buttons
87
+
88
+ names.each do |name|
89
+
90
+ define_singleton_method name.to_sym do
91
+ buttons[name].click
92
+ @browser.network.wait_for_idle
93
+ sleep = 1
94
+ self
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
54
101
  def fetch_links()
102
+
103
+ all_links = @doc.root.xpath('//a')
55
104
 
56
- b = @browser
57
- doc = Rexle.new b.body
58
- all_links = doc.root.xpath('//a')
59
-
105
+ all_links.each do |x|
106
+
107
+ if x.plaintext.empty? then
108
+ x.text = x.attributes[:href].sub(/\.\w+$/,'')[/([^\/]+)$/].split(/[_]|(?=[A-Z])/).join(' ')
109
+ else
110
+ x.text = x.plaintext.gsub('&amp;','&')
111
+ end
112
+
113
+ end
114
+
60
115
  valid_links = all_links.reject do |x|
61
116
 
62
117
  puts 'x: ' + x.inspect if @debug
63
- s = x.plaintext.gsub('&amp;','&')
64
- r = (x.attributes[:target] == '_blank') | s.empty?
118
+ r = (x.attributes[:target] == '_blank')
65
119
 
66
120
  puts 'r: ' + r.inspect if @debug
67
121
  r
68
122
 
69
- end.map {|x| all_links.index x}
123
+ end
124
+ indices = valid_links.map {|x| all_links.index x}
70
125
 
71
- active_links = b.xpath('//a')
72
- valid_active_links = valid_links.map {|n| active_links[n]}
126
+ active_links = @browser.xpath('//a')
127
+ valid_active_links = indices.map {|n| active_links[n]}
73
128
 
74
129
 
75
- @links = valid_active_links.flat_map do |x|
76
- a = x.text.split(/\W+/).map {|label| [label, x]} << [x.text, x]
130
+ @links = valid_active_links.flat_map.with_index do |x, i|
131
+
132
+ a = valid_links[i].text.split(/\W+/).map {|label| [label, x]}
133
+ a << [valid_links[i].text, x]
134
+
135
+ puts 'a: ' + a.inspect if @debug
77
136
  a + a.map {|x, obj| [x.downcase, obj]}
78
137
  end.to_h
79
138
 
80
- names = @links.keys.map(&:downcase).uniq.select {|x| x =~ /^\w+$/}
139
+ names = @links.keys.map(&:downcase).uniq.select {|x| x =~ /^[\w ]+$/}
81
140
  links = @links
82
141
 
83
142
  names.each do |name|
84
143
 
85
- define_singleton_method name.to_sym do
144
+ define_singleton_method name.gsub(/ +/,'_').to_sym do
86
145
  links[name].click
87
- sleep 3
146
+ sleep 1
147
+ scan_page()
88
148
  self
89
149
  end
90
150
 
91
151
  end
92
152
 
93
- end
153
+ end
154
+
155
+ def scan_form_elements()
156
+
157
+ # find radio buttons
158
+
159
+ #a = doc.root.xpath('//input[@type="radio"]')
160
+ a = @browser.xpath('//input[@type="radio"]')
161
+ #h = a.group_by {|x| x.attributes[:name]}
162
+ h = a.group_by {|x| x.attribute('name')}
163
+ @radio = h.values
164
+ define_singleton_method(:on) { @radio[0][0].click; self }
165
+ define_singleton_method(:off) { @radio[0][1].click; self }
166
+
167
+ fetch_buttons()
168
+
169
+ end
170
+
171
+ def scan_js_links()
172
+
173
+ @js_methods = {}
174
+ b = @browser
175
+
176
+ b.xpath('//a').select {|x| x.attribute('href') =~ /^javascript/}.each do |e|
177
+
178
+
179
+ s = e.attribute('href')[/(?<=^javascript:)[^\(]+/]
180
+ puts 's: ' + s.inspect
181
+ a = s.split(/\W+|(?=[A-Z])/).map {|label| [label, s]}
182
+ a << [s, s]
183
+ a << [s.split(/\W+|(?=[A-Z])/).join('_'), s]
184
+ a << [s.split(/\W+|(?=[A-Z])/).join('_').downcase, s]
185
+ #@js_methods[s] = a
186
+
187
+ a.concat a.map {|x, name| [x.downcase, name] }
188
+
189
+ puts 'a: ' + a.inspect
190
+
191
+ a.uniq.select {|x, _| x =~ /^[a-z0-9_]+$/}.each do |x, name|
192
+
193
+ if @debug then
194
+ puts 'x: ' + x.inspect
195
+ puts 'name: ' + name.inspect
196
+ end
197
+
198
+ define_singleton_method(x.to_sym) do |*args|
199
+ #args = raw_args.map {|x| x[/^[0-9]+$/] ? x.to_i : x}
200
+ js_method = "%s(%s)" % [name, args.map(&:inspect).join(', ')]
201
+ puts 'js_method: ' + js_method.inspect if @debug
202
+ @browser.evaluate(js_method)
203
+ @browser.network.wait_for_idle
204
+ sleep 4
205
+ self.scan_page()
206
+ end
207
+
208
+ end
209
+
210
+ end
211
+ end
94
212
 
95
213
  def method_missing(method_name, *args)
96
214
 
215
+ puts 'method_missing: ' + method_name.inspect if @debug
97
216
  node = @browser.at_css '.' + method_name.to_s
98
217
  node.text if node
99
218
 
100
219
  end
101
220
 
102
221
  end
103
-
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ferrumwizard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,7 +35,7 @@ cert_chain:
35
35
  7e24hNRMt3t/JE9ogEO4JzFUH2vq2zzR5X9JQqEclWfwHi4cf8bZFJ7spjZQPjSZ
36
36
  Ok3rs0A+kW4ixAj1rDYuoyG/
37
37
  -----END CERTIFICATE-----
38
- date: 2020-07-30 00:00:00.000000000 Z
38
+ date: 2020-08-01 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rexle
metadata.gz.sig CHANGED
Binary file