isomorfeus-puppetmaster 0.3.2 → 0.3.3

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
  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