isomorfeus-puppetmaster 0.3.2 → 0.3.3

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: 427ff7db65720f0b8a7adbde4778b89700671dee6f35a1b766606573b0477a4a
4
- data.tar.gz: dc73b15d323e81353786ae448f631f1cc61e368e6823eb1ea5fddfbc92483feb
3
+ metadata.gz: f1a369c88fa52e50d5258aad78591bcd079723ae8b31c1060829113f4cfc5323
4
+ data.tar.gz: b420d2cce1ad70c3cf02e9afbe376e2d8ac4e8fda259a80d8b97bbdcdb5f5006
5
5
  SHA512:
6
- metadata.gz: 60087609ceac68c2e7f5c92f0501b07db013637ef93152aee9235bb0538c9912672a4f5cb641bc809e8039378636bea6869854a2c35e4b37601695d94890a9ab
7
- data.tar.gz: 9f60ee61889b2538f48674b2f1faf256ffc937a687fd62616953f9edb5c6ba66538683c40b5334530033f5ef1ac86de1d29ef7dab989c04fa9482a08a8f6e2ea
6
+ metadata.gz: 6f1fd308a029db3d5d278906ff4f12957388c6e6c0588aeecfa47e420af518817b53ef7077d9fba1f2bf02b5aa99dd651e05f459abc822f47114137542b3851e
7
+ data.tar.gz: d3c77ebab0d357c9aa6b1d47f18e66baed051fd4a9361c5636a3eba60a860841a5c13d479e4189d6440d6648657fbde71972f6a3c3758eb1db00912a16c41a7b
@@ -36,9 +36,6 @@ require 'isomorfeus/puppetmaster/iframe'
36
36
  require 'isomorfeus/puppetmaster/driver/puppeteer_document'
37
37
  require 'isomorfeus/puppetmaster/driver/puppeteer_node'
38
38
  require 'isomorfeus/puppetmaster/driver/puppeteer'
39
- require 'isomorfeus/puppetmaster/driver/jsdom_document'
40
- require 'isomorfeus/puppetmaster/driver/jsdom_node'
41
- require 'isomorfeus/puppetmaster/driver/jsdom'
42
39
  require 'isomorfeus/puppetmaster/driver_registration'
43
40
  require 'isomorfeus/puppetmaster/server/executor_middleware'
44
41
  require 'isomorfeus/puppetmaster/server/middleware'
@@ -46,4 +43,4 @@ require 'isomorfeus/puppetmaster/server/checker'
46
43
  require 'isomorfeus/puppetmaster/server'
47
44
  require 'isomorfeus/puppetmaster/server_registration'
48
45
 
49
- require 'isomorfeus/puppetmaster/dsl'
46
+ require 'isomorfeus/puppetmaster/dsl'
@@ -100,7 +100,7 @@ module Isomorfeus
100
100
  start = Time.now
101
101
  until have_result do
102
102
  raise "await_ruby: execution timed out! Is Opal available?" if (Time.now - start) > 30
103
- have_result = evaluate_script 'Opal.gvars.promise_resolved'
103
+ have_result = evaluate_script 'Opal ? Opal.gvars.promise_resolved : null'
104
104
  sleep 0.1 unless have_result
105
105
  end
106
106
  result, exception = execute_script <<~JAVASCRIPT
@@ -196,18 +196,16 @@ module Isomorfeus
196
196
  def await(script)
197
197
  @context.eval <<~JAVASCRIPT
198
198
  (async () => {
199
- try {
200
- LastExecutionFinished = false;
201
- LastResult = null;
202
- LastErr = null;
203
- #{script}
204
- LastExecutionFinished = true;
205
- } catch(err) {
206
- LastResult = null;
207
- LastErr = err;
208
- LastExecutionFinished = true;
209
- }
210
- })()
199
+ LastExecutionFinished = false;
200
+ LastResult = null;
201
+ LastErr = null;
202
+ #{script}
203
+ LastExecutionFinished = true;
204
+ })().catch(function(err) {
205
+ LastResult = null;
206
+ LastErr = err;
207
+ LastExecutionFinished = true;
208
+ })
211
209
  JAVASCRIPT
212
210
  await_result
213
211
  end
@@ -226,20 +224,23 @@ module Isomorfeus
226
224
  JAVASCRIPT
227
225
  end
228
226
 
229
- def determine_error(message)
230
- if message.include?('net::ERR_CERT_') || message.include?('SEC_ERROR_EXPIRED_CERTIFICATE')
231
- Isomorfeus::Puppetmaster::CertificateError.new(message)
232
- elsif message.include?('net::ERR_NAME_') || message.include?('NS_ERROR_UNKNOWN_HOST')
233
- Isomorfeus::Puppetmaster::DNSError.new(message)
234
- elsif message.include?('Unknown key: ')
235
- Isomorfeus::Puppetmaster::KeyError.new(message)
236
- elsif message.include?('Execution context was destroyed, most likely because of a navigation.')
237
- Isomorfeus::Puppetmaster::ExecutionContextError.new(message)
238
- elsif message.include?('Evaluation failed: DOMException:') || (message.include?('Evaluation failed:') && (message.include?('is not a valid selector') || message.include?('is not a legal expression')))
239
- Isomorfeus::Puppetmaster::DOMException.new(message)
240
- else
241
- Isomorfeus::Puppetmaster::JavaScriptError.new(message)
242
- end
227
+ def determine_error(error)
228
+ message = "#{error['name']}: #{error['message']}"
229
+ exception = if message.include?('net::ERR_CERT_') || message.include?('SEC_ERROR_EXPIRED_CERTIFICATE')
230
+ Isomorfeus::Puppetmaster::CertificateError.new(message)
231
+ elsif message.include?('net::ERR_NAME_') || message.include?('NS_ERROR_UNKNOWN_HOST')
232
+ Isomorfeus::Puppetmaster::DNSError.new(message)
233
+ elsif message.include?('Unknown key: ')
234
+ Isomorfeus::Puppetmaster::KeyError.new(message)
235
+ elsif message.include?('Execution context was destroyed, most likely because of a navigation.')
236
+ Isomorfeus::Puppetmaster::ExecutionContextError.new(message)
237
+ elsif message.include?('Evaluation failed: DOMException:') || (message.include?('Evaluation failed:') && (message.include?('is not a valid selector') || message.include?('is not a legal expression')))
238
+ Isomorfeus::Puppetmaster::DOMException.new(message)
239
+ else
240
+ Isomorfeus::Puppetmaster::JavaScriptError.new(message)
241
+ end
242
+ exception.set_backtrace(error['stack'])
243
+ exception
243
244
  end
244
245
 
245
246
  def execution_finished?
@@ -247,8 +248,8 @@ module Isomorfeus
247
248
  end
248
249
 
249
250
  def get_result
250
- res, err_msg = @context.eval 'GetLastResult()'
251
- raise determine_error(err_msg) if err_msg
251
+ res, error = @context.eval 'GetLastResult()'
252
+ raise determine_error(error) if error && !error.empty?
252
253
  res
253
254
  end
254
255
 
@@ -307,11 +308,12 @@ module Isomorfeus
307
308
  LastRes = null;
308
309
  LastExecutionFinished = false;
309
310
 
310
- if (err) { return [null, err.toString() + "\\n" + err.stack]; }
311
+ if (err) { return [null, {name: err.name, message: err.message, stack: err.stack}]; }
311
312
  else { return [res, null]; }
312
313
 
313
314
  } else {
314
- return [null, (new Error('Last command did not yet finish execution!')).message];
315
+ var new_err = new Error('Last command did not yet finish execution!');
316
+ return [null, {name: new_err.name, message: new_err.message, stack: new_err.stack}];
315
317
  }
316
318
  };
317
319
 
@@ -374,7 +376,10 @@ module Isomorfeus
374
376
  LastErr = err;
375
377
  LastExecutionFinished = true;
376
378
  }
377
- })();
379
+ })().catch(function(err) {
380
+ LastErr = err;
381
+ LastExecutionFinished = true;
382
+ });
378
383
  JAVASCRIPT
379
384
  end
380
385
 
@@ -310,17 +310,35 @@ module Isomorfeus
310
310
 
311
311
  def document_evaluate_script(document, script, *args)
312
312
  await <<~JAVASCRIPT
313
- LastResult = await AllPageHandles[#{document.handle}].evaluate((arguments) => {
314
- return #{script.strip}
313
+ var result = await AllPageHandles[#{document.handle}].evaluate((arguments) => {
314
+ try {
315
+ var res = (function(arguments) {
316
+ return #{script.strip};
317
+ })(arguments);
318
+ return [res, null];
319
+ } catch (err) {
320
+ return [null, {name: err.name, message: err.message, stack: err.stack}];
321
+ }
315
322
  }, #{args});
323
+ LastResult = result[0];
324
+ LastErr = result[1];
316
325
  JAVASCRIPT
317
326
  end
318
327
 
319
328
  def document_execute_script(document, script, *args)
320
329
  await <<~JAVASCRIPT
321
- LastResult = await AllPageHandles[#{document.handle}].evaluate((arguments) => {
322
- #{script.strip}
330
+ var result = await AllPageHandles[#{document.handle}].evaluate((arguments) => {
331
+ try {
332
+ var res = (function(arguments) {
333
+ #{script.strip};
334
+ })(arguments);
335
+ return [res, null];
336
+ } catch (err) {
337
+ return [null, {name: err.name, message: err.message, stack: err.stack}];
338
+ }
323
339
  }, #{args});
340
+ LastResult = result[0];
341
+ LastErr = result[1];
324
342
  JAVASCRIPT
325
343
  end
326
344
 
@@ -454,7 +472,7 @@ module Isomorfeus
454
472
  }
455
473
  JAVASCRIPT
456
474
  con_messages = messages.map {|m| Isomorfeus::Puppetmaster::ConsoleMessage.new(m)}
457
- con_messages.each { |m| raise determine_error(m.text) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
475
+ con_messages.each { |m| raise determine_error({ 'message' => m.text }) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
458
476
  if response_hash
459
477
  response = Isomorfeus::Puppetmaster::Response.new(response_hash)
460
478
  document.instance_variable_set(:@response, response)
@@ -491,7 +509,7 @@ module Isomorfeus
491
509
  }
492
510
  JAVASCRIPT
493
511
  con_messages = messages.map {|m| Isomorfeus::Puppetmaster::ConsoleMessage.new(m)}
494
- con_messages.each { |m| raise determine_error(m.text) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
512
+ con_messages.each { |m| raise determine_error({ 'message' => m.text }) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
495
513
  if response_hash
496
514
  response = Isomorfeus::Puppetmaster::Response.new(response_hash)
497
515
  document.instance_variable_set(:@response, response)
@@ -532,7 +550,7 @@ module Isomorfeus
532
550
  }
533
551
  JAVASCRIPT
534
552
  con_messages = messages.map {|m| Isomorfeus::Puppetmaster::ConsoleMessage.new(m)}
535
- con_messages.each { |m| raise determine_error(m.text) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
553
+ con_messages.each { |m| raise determine_error({ 'message' => m.text }) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
536
554
  if response_hash
537
555
  response = Isomorfeus::Puppetmaster::Response.new(response_hash)
538
556
  document.instance_variable_set(:@response, response)
@@ -610,7 +628,7 @@ module Isomorfeus
610
628
  LastResult = [page_handle, result_response, ConsoleMessages[page_handle]];
611
629
  JAVASCRIPT
612
630
  con_messages = messages.map {|m| Isomorfeus::Puppetmaster::ConsoleMessage.new(m)}
613
- con_messages.each { |m| raise determine_error(m.text) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
631
+ con_messages.each { |m| raise determine_error({ 'message' => m.text }) if m.level == 'error' && !m.text.start_with?('Failed to load resource:') }
614
632
  Isomorfeus::Puppetmaster::Document.new(self, handle, Isomorfeus::Puppetmaster::Response.new(response_hash))
615
633
  end
616
634
 
@@ -9,11 +9,3 @@ end
9
9
  Isomorfeus::Puppetmaster.register_driver(:chromium_debug) do |app|
10
10
  Isomorfeus::Puppetmaster::Driver::Puppeteer.new(browser_type: :chromium, headless: false, devtools: true, app: app)
11
11
  end
12
-
13
- Isomorfeus::Puppetmaster.register_driver(:jsdom) do |app|
14
- Isomorfeus::Puppetmaster::Driver::Jsdom.new(app: app)
15
- end
16
-
17
- Isomorfeus::Puppetmaster.register_driver(:jsdom_canvas) do |app|
18
- Isomorfeus::Puppetmaster::Driver::Jsdom.new(app: app, canvas: true)
19
- end
@@ -66,18 +66,22 @@ module Isomorfeus
66
66
  ruby_source = Isomorfeus::Puppetmaster.block_source_code(&block) if block_given?
67
67
  request_hash = { 'key' => @request_key, 'code' => ruby_source }
68
68
  response = if using_ssl?
69
- http = Net::HTTP.start(@host, @port, { use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE })
70
- http.post('/__executor__', Oj.dump(request_hash, {}))
71
- else
72
- http = Net::HTTP.start(@host, @port)
73
- http.post('/__executor__', Oj.dump(request_hash, {}))
74
- end
69
+ http = Net::HTTP.start(@host, @port, { use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE })
70
+ http.post('/__executor__', Oj.dump(request_hash, mode: :strict))
71
+ else
72
+ http = Net::HTTP.start(@host, @port)
73
+ http.post('/__executor__', Oj.dump(request_hash, mode: :strict))
74
+ end
75
75
  if response.code == '200'
76
- result_hash = Oj.load(response.body, {})
77
- raise result_hash['error'] if result_hash.has_key?('error')
76
+ result_hash = Oj.load(response.body)
77
+ if result_hash.has_key?('error')
78
+ error = RuntimeError.new(result_hash['error'])
79
+ error.set_backtrace(result_hash['backtrace'])
80
+ raise error
81
+ end
78
82
  result_hash['result']
79
83
  else
80
- raise 'A error occured.'
84
+ raise 'A error occurred.'
81
85
  end
82
86
  end
83
87
 
@@ -14,18 +14,27 @@ module Isomorfeus
14
14
  def call(env)
15
15
  if env['PATH_INFO'] == '/__executor__' && env['REQUEST_METHOD'] == 'POST'
16
16
  request = Rack::Request.new(env)
17
+ response = nil
17
18
  unless request.body.nil?
18
- request_hash = Oj.load(request.body.read, {})
19
+ request_hash = Oj.load(request.body.read, mode: :strict)
19
20
  if request_hash['key'] != @@request_key
20
- Rack::Response.new(Oj.dump({ 'error' => 'wrong key given, execution denied' }, {}), 401, 'Content-Type' => 'application/json').finish
21
+ response = Rack::Response.new(Oj.dump({ 'error' => 'wrong key given, execution denied' }),
22
+ 401,
23
+ 'Content-Type' => 'application/json')
24
+ else
25
+ begin
26
+ result = TOPLEVEL_BINDING.eval('self').instance_eval(request_hash['code']) if request_hash['code']
27
+ response = Rack::Response.new(Oj.dump({ 'result' => result }),
28
+ 200,
29
+ 'Content-Type' => 'application/json')
30
+ rescue Exception => e
31
+ response = Rack::Response.new(Oj.dump({ 'error' => "#{e.class}: #{e.message}", 'backtrace' => e.backtrace.join("\n") }),
32
+ 200,
33
+ 'Content-Type' => 'application/json')
34
+ end
21
35
  end
22
- begin
23
- result = Object.instance_eval(request_hash['code']) if request_hash['code']
24
- rescue Exception => e
25
- Rack::Response.new(Oj.dump({ 'error' => "#{e.class}: #{e.message}" }, {}), 200, 'Content-Type' => 'application/json').finish
26
- end
27
- Rack::Response.new(Oj.dump({ 'result' => result }, {}), 200, 'Content-Type' => 'application/json').finish
28
36
  end
37
+ response.finish
29
38
  else
30
39
  @app.call(env)
31
40
  end
@@ -1,3 +1,3 @@
1
1
  module Isomorfeus
2
- PUPPETMASTER_VERSION = '0.3.2'
2
+ PUPPETMASTER_VERSION = '0.3.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isomorfeus-puppetmaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-17 00:00:00.000000000 Z
11
+ date: 2020-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: oj
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 3.10.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 3.10.1
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: opal
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +128,14 @@ dependencies:
114
128
  requirements:
115
129
  - - "~>"
116
130
  - !ruby/object:Gem::Version
117
- version: 2.11.3
131
+ version: 2.11.7
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
136
  - - "~>"
123
137
  - !ruby/object:Gem::Version
124
- version: 2.11.3
138
+ version: 2.11.7
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: chunky_png
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +184,14 @@ dependencies:
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: 0.7.36
187
+ version: 0.7.38
174
188
  type: :development
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: 0.7.36
194
+ version: 0.7.38
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: irb
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -317,9 +331,6 @@ files:
317
331
  - lib/isomorfeus/puppetmaster/console_message.rb
318
332
  - lib/isomorfeus/puppetmaster/cookie.rb
319
333
  - lib/isomorfeus/puppetmaster/document.rb
320
- - lib/isomorfeus/puppetmaster/driver/jsdom.rb
321
- - lib/isomorfeus/puppetmaster/driver/jsdom_document.rb
322
- - lib/isomorfeus/puppetmaster/driver/jsdom_node.rb
323
334
  - lib/isomorfeus/puppetmaster/driver/puppeteer.rb
324
335
  - lib/isomorfeus/puppetmaster/driver/puppeteer_document.rb
325
336
  - lib/isomorfeus/puppetmaster/driver/puppeteer_node.rb
@@ -1,373 +0,0 @@
1
- module Isomorfeus
2
- module Puppetmaster
3
- module Driver
4
- class Jsdom
5
- include Isomorfeus::Puppetmaster::Driver::JsdomDocument
6
- include Isomorfeus::Puppetmaster::Driver::JsdomNode
7
-
8
- VIEWPORT_DEFAULT_WIDTH = 1024
9
- VIEWPORT_DEFAULT_HEIGHT = 768
10
- VIEWPORT_MAX_WIDTH = 1366
11
- VIEWPORT_MAX_HEIGHT = 768
12
- TIMEOUT = 30 # seconds
13
- REACTION_TIMEOUT = 0.5
14
- EVENTS = {
15
- blur: ['FocusEvent', {}],
16
- focus: ['FocusEvent', {}],
17
- focusin: ['FocusEvent', { bubbles: true }],
18
- focusout: ['FocusEvent', { bubbles: true }],
19
- click: ['MouseEvent', { bubbles: true, cancelable: true }],
20
- dblckick: ['MouseEvent', { bubbles: true, cancelable: true }],
21
- mousedown: ['MouseEvent', { bubbles: true, cancelable: true }],
22
- mouseup: ['MouseEvent', { bubbles: true, cancelable: true }],
23
- mouseenter: ['MouseEvent', {}],
24
- mouseleave: ['MouseEvent', {}],
25
- mousemove: ['MouseEvent', { bubbles: true, cancelable: true }],
26
- mouseover: ['MouseEvent', { bubbles: true, cancelable: true }],
27
- mouseout: ['MouseEvent', { bubbles: true, cancelable: true }],
28
- context_menu: ['MouseEvent', { bubble: true, cancelable: true }],
29
- submit: ['Event', { bubbles: true, cancelable: true }],
30
- change: ['Event', { bubbles: true, cacnelable: false }],
31
- input: ['InputEvent', { bubbles: true, cacnelable: false }],
32
- wheel: ['WheelEvent', { bubbles: true, cancelable: true }]
33
- }.freeze
34
-
35
- attr_accessor :default_document
36
-
37
- def initialize(options = {})
38
- @app = options.delete(:app)
39
- @options = options.dup
40
- @canvas = @options.delete(:canvas) { false }
41
- @ignore_https_errors = !!@options.delete(:ignore_https_errors)
42
- @max_width = @options.delete(:max_width) { VIEWPORT_MAX_WIDTH }
43
- @max_height = @options.delete(:max_height) { VIEWPORT_MAX_HEIGHT }
44
- @width = @options.delete(:width) { VIEWPORT_DEFAULT_WIDTH > @max_width ? @max_width : VIEWPORT_DEFAULT_WIDTH }
45
- @height = @options.delete(:height) { VIEWPORT_DEFAULT_HEIGHT > @max_height ? @max_height : VIEWPORT_DEFAULT_HEIGHT }
46
- @timeout = @options.delete(:timeout) { TIMEOUT }
47
- @max_wait = @options.delete(:max_wait) { @timeout + 1 }
48
- @reaction_timeout = @options.delete(:reaction_timeout) { REACTION_TIMEOUT }
49
- @jsdom_timeout = @timeout * 1000
50
- @jsdom_reaction_timeout = @reaction_timeout * 1000
51
- @url_blacklist = @options.delete(:url_blacklist) { [] }
52
- @context = ExecJS.permissive_compile(jsdom_launch)
53
- page_handle, @browser = await_result
54
- @default_document = Isomorfeus::Puppetmaster::Document.new(self, page_handle, Isomorfeus::Puppetmaster::Response.new('status' => 200))
55
- end
56
-
57
- def self.document_handle_disposer(driver, handle)
58
- cjs = <<~JAVASCRIPT
59
- delete AllDomHandles[#{handle}];
60
- delete ConsoleMessages[#{handle}];
61
- JAVASCRIPT
62
- proc { driver.execute_script(cjs) }
63
- end
64
-
65
- def self.node_handle_disposer(driver, handle)
66
- cjs = <<~JAVASCRIPT
67
- if (AllElementHandles[#{handle}]) { AllElementHandles[#{handle}].dispose(); }
68
- delete AllElementHandles[#{handle}];
69
- JAVASCRIPT
70
- proc { driver.execute_script(cjs) }
71
- end
72
-
73
- def browser
74
- @browser
75
- end
76
-
77
- def document_handles
78
- @context.eval 'Object.keys(AllDomHandles)'
79
- end
80
-
81
- ##### frame, all todo
82
-
83
- def frame_all_text(frame)
84
- await <<~JAVASCRIPT
85
- LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
86
- return frame.contentDocument.documentElement.textContent;
87
- }, AllElementHandles[#{frame.handle}]);
88
- JAVASCRIPT
89
- end
90
-
91
- def frame_body(frame)
92
- node_data = await <<~JAVASCRIPT
93
- var tt = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
94
- node = frame.contentDocument.body;
95
- var name = node.nodeName;
96
- var tag = node.tagName.toLowerCase();
97
- var type = null;
98
- if (tag === 'input') { type = node.getAttribute('type'); }
99
- return [name, tag, type];
100
- }, AllElementHandles[#{frame.handle}]);
101
- LastResult = {handle: node_handle, name: tt[0], tag: tt[1], type: tt[2]};
102
- JAVASCRIPT
103
- if node_data
104
- node_data[:css_selector] = 'body'
105
- Isomorfeus::Puppetmaster::Node.new_by_tag(self, document, node_data)
106
- end
107
- end
108
-
109
- def frame_focus(frame)
110
- await <<~JAVASCRIPT
111
- await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
112
- frame.contentDocument.documentElement.focus();
113
- }, AllElementHandles[#{frame.handle}]);
114
- JAVASCRIPT
115
- end
116
-
117
- def frame_head(frame)
118
- node_data = await <<~JAVASCRIPT
119
- var tt = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
120
- node = frame.contentDocument.head;
121
- var name = node.nodeName;
122
- var tag = node.tagName.toLowerCase();
123
- var type = null;
124
- if (tag === 'input') { type = node.getAttribute('type'); }
125
- return [name, tag, type];
126
- }, AllElementHandles[#{frame.handle}]);
127
- LastResult = {handle: node_handle, name: tt[0], tag: tt[1], type: tt[2]};
128
- JAVASCRIPT
129
- if node_data
130
- node_data[:css_selector] = 'body'
131
- Isomorfeus::Puppetmaster::Node.new_by_tag(self, document, node_data)
132
- end
133
- end
134
-
135
- def frame_html(frame)
136
- await <<~JAVASCRIPT
137
- LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
138
- return frame.contentDocument.documentElement.outerHTML;
139
- }, AllElementHandles[#{frame.handle}]);
140
- JAVASCRIPT
141
- end
142
-
143
- def frame_title(frame)
144
- await <<~JAVASCRIPT
145
- LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
146
- return frame.contentDocument.title;
147
- }, AllElementHandles[#{frame.handle}]);
148
- JAVASCRIPT
149
- end
150
-
151
- def frame_url(frame)
152
- await <<~JAVASCRIPT
153
- LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
154
- return frame.contentDocument.location.href;
155
- }, AllElementHandles[#{frame.handle}]);
156
- JAVASCRIPT
157
- end
158
-
159
- def frame_visible_text(frame)
160
- # if node is AREA, check visibility of relevant image
161
- text = await <<~JAVASCRIPT
162
- LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
163
- var node = frame.contentDocument.body;
164
- var temp_node = node;
165
- while (temp_node) {
166
- style = window.getComputedStyle(node);
167
- if (style.display === "none" || style.visibility === "hidden" || parseFloat(style.opacity) === 0) { return ''; }
168
- temp_node = temp_node.parentElement;
169
- }
170
- if (node.nodeName == "TEXTAREA" || node instanceof SVGElement) { return node.textContent; }
171
- else { return node.innerText; }
172
- }, AllElementHandles[#{frame.handle}]);
173
- JAVASCRIPT
174
- text.gsub(/\A[[:space:]&&[^\u00a0]]+/, "").gsub(/[[:space:]&&[^\u00a0]]+\z/, "").gsub(/\n+/, "\n").tr("\u00a0", " ")
175
- end
176
-
177
- private
178
-
179
- def need_alt?(modifiers)
180
- (modifiers & %i[alt alt_left alt_right]).size > 0
181
- end
182
-
183
- def need_control?(modifiers)
184
- (modifiers & %i[control control_left control_rigth]).size > 0
185
- end
186
-
187
- def need_meta?(modifiers)
188
- (modifiers & %i[meta meta_left meta_right]).size > 0
189
- end
190
-
191
- def need_shift?(modifiers)
192
- (modifiers & %i[shift shift_left shift_right]).size > 0
193
- end
194
-
195
- def await(script)
196
- @context.eval <<~JAVASCRIPT
197
- (async () => {
198
- try {
199
- LastExecutionFinished = false;
200
- LastResult = null;
201
- LastErr = null;
202
- #{script}
203
- LastExecutionFinished = true;
204
- } catch(err) {
205
- LastResult = null;
206
- LastErr = err;
207
- LastExecutionFinished = true;
208
- }
209
- })()
210
- JAVASCRIPT
211
- await_result
212
- end
213
-
214
- def await_result
215
- start_time = Time.now
216
- while !execution_finished? && !timed_out?(start_time)
217
- sleep 0.01
218
- end
219
- get_result
220
- end
221
-
222
- def determine_error(message)
223
- if message.include?('Error: certificate has expired')
224
- Isomorfeus::Puppetmaster::CertificateError.new(message) unless @ignore_https_errors
225
- elsif message.include?('Error: getaddrinfo')
226
- Isomorfeus::Puppetmaster::DNSError.new(message)
227
- elsif message.include?('Unknown key: ')
228
- Isomorfeus::Puppetmaster::KeyError.new(message)
229
- elsif message.include?('Execution context was destroyed, most likely because of a navigation.')
230
- Isomorfeus::Puppetmaster::ExecutionContextError.new(message)
231
- elsif message.include?('Unable to find ')
232
- Isomorfeus::Puppetmaster::ElementNotFound.new(message)
233
- elsif (message.include?('SyntaxError:') && (message.include?('unknown pseudo-class selector') || message.include?('is not a valid selector'))) || message.include?('invalid xpath query')
234
- Isomorfeus::Puppetmaster::DOMException.new(message)
235
- else
236
- Isomorfeus::Puppetmaster::JavaScriptError.new(message)
237
- end
238
- end
239
-
240
- def execution_finished?
241
- @context.eval 'LastExecutionFinished'
242
- end
243
-
244
- def get_result
245
- res, err_msg = @context.eval 'GetLastResult()'
246
- raise determine_error(err_msg) if err_msg
247
- res
248
- end
249
-
250
- def jsdom_launch
251
- <<~JAVASCRIPT
252
- #{"const canvas = require('canvas');" if @canvas}
253
- const jsdom = require('jsdom');
254
- const Cookie = jsdom.toughCookie.Cookie;
255
- const MemoryCookieStore = jsdom.toughCookie.MemoryCookieStore;
256
- const { JSDOM } = jsdom;
257
-
258
- const JSDOMOptions = {pretendToBeVisual: true, resources: 'usable', runScripts: 'dangerously'};
259
-
260
- var LastResponse = null;
261
- var LastResult = null;
262
- var LastErr = null;
263
- var LastExecutionFinished = false;
264
- var LastHandleId = 0;
265
-
266
- var AllDomHandles = {};
267
- var AllElementHandles = {};
268
- var AllConsoleHandles = {};
269
- var ConsoleMessages = {};
270
-
271
- var ModalText = null;
272
- var ModalTextMatched = false;
273
-
274
- const GetLastResult = function() {
275
- if (LastExecutionFinished === true) {
276
- var err = LastErr;
277
- var res = LastResult;
278
-
279
- LastErr = null;
280
- LastRes = null;
281
- LastExecutionFinished = false;
282
-
283
- if (err) { return [null, err.toString() + "\\n" + err.stack]; }
284
- else { return [res, null]; }
285
-
286
- } else {
287
- return [null, (new Error('Last command did not yet finish execution!')).message];
288
- }
289
- };
290
-
291
- const DialogAcceptHandler = async (dialog) => {
292
- var msg = dialog.message()
293
- ModalTextMatched = (ModalText === msg);
294
- ModalText = msg;
295
- await dialog.accept();
296
- }
297
-
298
- const DialogDismissHandler = async (dialog) => {
299
- var msg = dialog.message()
300
- ModalTextMatched = (ModalText === msg);
301
- ModalText = msg;
302
- await dialog.dismiss();
303
- }
304
-
305
- const RegisterElementHandle = function(element_handle) {
306
- var entries = Object.entries(AllElementHandles);
307
- for(var i = 0; i < entries.length; i++) {
308
- if (entries[i][1] === element_handle) { return entries[i][0]; }
309
- }
310
- LastHandleId++;
311
- AllElementHandles[LastHandleId] = element_handle;
312
- return LastHandleId;
313
- };
314
-
315
- const RegisterElementHandleArray = function(element_handle_array) {
316
- var registered_handles = [];
317
- element_handle_array.forEach(function(handle){
318
- registered_handles.push(RegisterElementHandle(handle));
319
- });
320
- return registered_handles;
321
- };
322
-
323
- const RegisterCon = function(con) {
324
- var entries = Object.entries(ConsoleMessages);
325
- for(var i = 0; i < entries.length; i++) {
326
- if (entries[i][1] === con) { return entries[i][0]; }
327
- }
328
- LastHandleId++;
329
- AllConsoleHandles[LastHandleId] = con;
330
- ConsoleMessages[LastHandleId] = [];
331
- return LastHandleId;
332
- };
333
- const RegisterDom = function(dom, handle_id) {
334
- var entries = Object.entries(AllDomHandles);
335
- for(var i = 0; i < entries.length; i++) {
336
- if (entries[i][1] === dom) { return entries[i][0]; }
337
- }
338
- AllDomHandles[handle_id] = dom;
339
- return handle_id;
340
- };
341
-
342
- (async () => {
343
- try {
344
- var con = new jsdom.VirtualConsole();
345
- var jar = new jsdom.CookieJar(new MemoryCookieStore(), {rejectPublicSuffixes: false, looseMode: true});
346
- var handle_id = RegisterCon(con);
347
- con.on('error', (msg) => { ConsoleMessages[handle_id].push({level: 'error', location: '', text: msg}); });
348
- con.on('warn', (msg) => { ConsoleMessages[handle_id].push({level: 'warn', location: '', text: msg}); });
349
- con.on('info', (msg) => { ConsoleMessages[handle_id].push({level: 'info', location: '', text: msg}); });
350
- con.on('log', (msg) => { ConsoleMessages[handle_id].push({level: 'dir', location: '', text: msg}); });
351
- con.on('debug', (msg) => { ConsoleMessages[handle_id].push({level: 'dir', location: '', text: msg}); });
352
- var dom = new JSDOM('', Object.assign({}, JSDOMOptions, { virtualConsole: con }));
353
- var browser = dom.window.navigator.userAgent;
354
- LastResult = [RegisterDom(dom, handle_id), browser];
355
- LastExecutionFinished = true;
356
- } catch (err) {
357
- LastErr = err;
358
- LastExecutionFinished = true;
359
- }
360
- })();
361
- JAVASCRIPT
362
- end
363
-
364
- def timed_out?(start_time)
365
- if (Time.now - start_time) > @timeout
366
- raise "Command Execution timed out!"
367
- end
368
- false
369
- end
370
- end
371
- end
372
- end
373
- end