Class: Isomorfeus::Puppetmaster::Driver::Puppeteer

Inherits:
Object
  • Object
show all
Includes:
PuppeteerDocument, PuppeteerNode
Defined in:
lib/isomorfeus/puppetmaster/driver/puppeteer.rb

Constant Summary collapse

VIEWPORT_DEFAULT_WIDTH =
1024
VIEWPORT_DEFAULT_HEIGHT =
768
VIEWPORT_MAX_WIDTH =
1366
VIEWPORT_MAX_HEIGHT =
768
TIMEOUT =

seconds

30
REACTION_TIMEOUT =
0.5
EVENTS =
{
  blur: ['FocusEvent', {}],
  focus: ['FocusEvent', {}],
  focusin: ['FocusEvent', { bubbles: true  }],
  focusout: ['FocusEvent', { bubbles: true }],
  click: ['MouseEvent', { bubbles: true, cancelable: true }],
  dblckick: ['MouseEvent', { bubbles: true, cancelable: true }],
  mousedown: ['MouseEvent', { bubbles: true, cancelable: true }],
  mouseup: ['MouseEvent', { bubbles: true, cancelable: true }],
  mouseenter: ['MouseEvent', {}],
  mouseleave: ['MouseEvent', {}],
  mousemove: ['MouseEvent', { bubbles: true, cancelable: true }],
  mouseover: ['MouseEvent', { bubbles: true, cancelable: true }],
  mouseout: ['MouseEvent', { bubbles: true, cancelable: true }],
  context_menu: ['MouseEvent', { bubble: true, cancelable: true }],
  submit: ['Event', { bubbles: true, cancelable: true }],
  change: ['Event', { bubbles: true, cacnelable: false }],
  input: ['InputEvent', { bubbles: true, cacnelable: false }],
  wheel: ['WheelEvent', { bubbles: true, cancelable: true }]
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PuppeteerNode

#node_all_text, #node_click, #node_disabled?, #node_dispatch_event, #node_double_click, #node_drag_to, #node_equal, #node_evaluate_script, #node_execute_script, #node_find, #node_find_all, #node_find_all_xpath, #node_find_xpath, #node_focus, #node_get_attribute, #node_get_property, #node_hover, #node_in_viewport?, #node_render_base64, #node_right_click, #node_save_screenshot, #node_scroll_by, #node_scroll_into_view, #node_scroll_to, #node_select, #node_style, #node_type_keys, #node_unselect, #node_value, #node_value=, #node_visible?, #node_visible_text, #node_wait_for, #node_wait_for_xpath

Methods included from PuppeteerDocument

#document_accept_alert, #document_accept_confirm, #document_accept_leave_page, #document_accept_prompt, #document_all_text, #document_body, #document_bring_to_front, #document_clear_authentication_credentials, #document_clear_cookies, #document_clear_extra_headers, #document_clear_url_blacklist, #document_click, #document_close, #document_console, #document_cookies, #document_dismiss_confirm, #document_dismiss_leave_page, #document_dismiss_prompt, #document_dispatch_event, #document_double_click, #document_evaluate_script, #document_execute_script, #document_find, #document_find_all, #document_find_all_xpath, #document_find_xpath, #document_go_back, #document_go_forward, #document_goto, #document_head, #document_html, #document_open_new_document, #document_reload, #document_remove_cookie, #document_render_base64, #document_reset_user_agent, #document_right_click, #document_save_pdf, #document_save_screenshot, #document_scroll_by, #document_scroll_to, #document_set_authentication_credentials, #document_set_cookie, #document_set_extra_headers, #document_set_url_blacklist, #document_set_user_agent, #document_title, #document_type_keys, #document_url, #document_user_agent, #document_viewport_maximize, #document_viewport_resize, #document_viewport_size, #document_wait_for, #document_wait_for_xpath

Constructor Details

#initialize(options = {}) ⇒ Puppeteer

Returns a new instance of Puppeteer.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 37

def initialize(options = {})
  # https://pptr.dev/#?product=Puppeteer&version=v1.12.2&show=api-puppeteerlaunchoptions
  # init ExecJs context
  @app = options.delete(:app)
  @options = options.dup
  @browser_type = @options.delete(:browser_type) { :chromium }
  @max_width = @options.delete(:max_width) { VIEWPORT_MAX_WIDTH }
  @max_height = @options.delete(:max_height) { VIEWPORT_MAX_HEIGHT }
  @width = @options.delete(:width) { VIEWPORT_DEFAULT_WIDTH > @max_width ? @max_width : VIEWPORT_DEFAULT_WIDTH }
  @height = @options.delete(:height) { VIEWPORT_DEFAULT_HEIGHT > @max_height ? @max_height : VIEWPORT_DEFAULT_HEIGHT }
  @timeout = @options.delete(:timeout) { TIMEOUT }
  @max_wait = @options.delete(:max_wait) { @timeout + 1 }
  @reaction_timeout = @options.delete(:reaction_timeout) { REACTION_TIMEOUT }
  @puppeteer_timeout = @timeout * 1000
  @puppeteer_reaction_timeout = @reaction_timeout * 1000
  @url_blacklist = @options.delete(:url_blacklist) { [] }
  @context = ExecJS.permissive_compile(puppeteer_launch)
  page_handle = await_result
  @default_document = Isomorfeus::Puppetmaster::Document.new(self, page_handle, Isomorfeus::Puppetmaster::Response.new('status' => 200))
  ObjectSpace.define_finalizer(self, self.class.close_browser(self))
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



35
36
37
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 35

def app
  @app
end

#default_documentObject

Returns the value of attribute default_document.



35
36
37
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 35

def default_document
  @default_document
end

#url_blacklistObject

Returns the value of attribute url_blacklist.



35
36
37
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 35

def url_blacklist
  @url_blacklist
end

Class Method Details

.document_handle_disposer(driver, handle) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 59

def self.document_handle_disposer(driver, handle)
  cjs = <<~JAVASCRIPT
    if (AllPageHandles[#{handle}]) { AllPageHandles[#{handle}].close(); }
    delete AllPageHandles[#{handle}];
    delete ConsoleMessages[#{handle}];
  JAVASCRIPT
  proc { driver.execute_script(cjs) }
end

.node_handle_disposer(driver, handle) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 68

def self.node_handle_disposer(driver, handle)
  cjs = <<~JAVASCRIPT
    if (AllElementHandles[#{handle}]) { AllElementHandles[#{handle}].dispose(); }
    delete AllElementHandles[#{handle}];
  JAVASCRIPT
  proc { driver.execute_script(cjs) }
end

Instance Method Details

#browserObject



76
77
78
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 76

def browser
  await('LastResult = await CurrentBrowser.userAgent();')
end

#document_handlesObject



80
81
82
83
84
85
86
87
88
89
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 80

def document_handles
  await <<~JAVASCRIPT
    var pages = await CurrentBrowser.pages();
    var handles = [];
    for (i=0; i< pages.length; i++) {
      handles.push(RegisterPage(pages[i]));
    }
    LastResult = handles;
  JAVASCRIPT
end

#frame_all_text(frame) ⇒ Object

frame, all todo



93
94
95
96
97
98
99
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 93

def frame_all_text(frame)
  await <<~JAVASCRIPT
    LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      return frame.contentDocument.documentElement.textContent;
    }, AllElementHandles[#{frame.handle}]);
  JAVASCRIPT
end

#frame_body(frame) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 101

def frame_body(frame)
  node_data = await <<~JAVASCRIPT
    var tt = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      node = frame.contentDocument.body;
      var name = node.nodeName;
      var tag = node.tagName.toLowerCase();
      var type = null;
      if (tag === 'input') { type = node.getAttribute('type'); }
      return [name, tag, type];
    }, AllElementHandles[#{frame.handle}]);
    LastResult = {handle: node_handle, name: tt[0], tag: tt[1], type: tt[2]};
  JAVASCRIPT
  if node_data
    node_data[:css_selector] = 'body'
    Isomorfeus::Puppetmaster::Node.new_by_tag(self, document, node_data)
  end
end

#frame_focus(frame) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 119

def frame_focus(frame)
  await <<~JAVASCRIPT
    await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      frame.contentDocument.documentElement.focus();
    }, AllElementHandles[#{frame.handle}]);
  JAVASCRIPT
end

#frame_head(frame) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 127

def frame_head(frame)
  node_data = await <<~JAVASCRIPT
    var tt = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      node = frame.contentDocument.head;
      var name = node.nodeName;
      var tag = node.tagName.toLowerCase();
      var type = null;
      if (tag === 'input') { type = node.getAttribute('type'); }
      return [name, tag, type];
    }, AllElementHandles[#{frame.handle}]);
    LastResult = {handle: node_handle, name: tt[0], tag: tt[1], type: tt[2]};
  JAVASCRIPT
  if node_data
    node_data[:css_selector] = 'body'
    Isomorfeus::Puppetmaster::Node.new_by_tag(self, document, node_data)
  end
end

#frame_html(frame) ⇒ Object



145
146
147
148
149
150
151
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 145

def frame_html(frame)
  await <<~JAVASCRIPT
    LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      return frame.contentDocument.documentElement.outerHTML;
    }, AllElementHandles[#{frame.handle}]);
  JAVASCRIPT
end

#frame_title(frame) ⇒ Object



153
154
155
156
157
158
159
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 153

def frame_title(frame)
  await <<~JAVASCRIPT
    LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      return frame.contentDocument.title;
    }, AllElementHandles[#{frame.handle}]);
  JAVASCRIPT
end

#frame_url(frame) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 161

def frame_url(frame)
  await <<~JAVASCRIPT
    LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      return frame.contentDocument.location.href;
    }, AllElementHandles[#{frame.handle}]);
  JAVASCRIPT
end

#frame_visible_text(frame) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/isomorfeus/puppetmaster/driver/puppeteer.rb', line 169

def frame_visible_text(frame)
  # if node is AREA, check visibility of relevant image
  text = await <<~JAVASCRIPT
    LastResult = await AllElementHandles[#{frame.handle}].executionContext().evaluate((frame) => {
      var node = frame.contentDocument.body;
      var temp_node = node;
      while (temp_node) {
        style = window.getComputedStyle(node);
        if (style.display === "none" || style.visibility === "hidden" || parseFloat(style.opacity) === 0) { return ''; }
        temp_node = temp_node.parentElement;
      }
      if (node.nodeName == "TEXTAREA" || node instanceof SVGElement) { return node.textContent; }
      else { return node.innerText; }
    }, AllElementHandles[#{frame.handle}]);
  JAVASCRIPT
  text.gsub(/\A[[:space:]&&[^\u00a0]]+/, "").gsub(/[[:space:]&&[^\u00a0]]+\z/, "").gsub(/\n+/, "\n").tr("\u00a0", " ")
end