Class: Puppeteer::DOMWorld
- Inherits:
-
Object
- Object
- Puppeteer::DOMWorld
- Defined in:
- lib/puppeteer/dom_world.rb
Overview
Defined Under Namespace
Classes: BindingFunction, DetachedError, ElementNotFoundError
Constant Summary collapse
- ADD_SCRIPT_URL =
<<~JAVASCRIPT async (url, type) => { const script = document.createElement('script'); script.src = url; if (type) script.type = type; const promise = new Promise((res, rej) => { script.onload = res; script.onerror = rej; }); document.head.appendChild(script); await promise; return script; } JAVASCRIPT
- ADD_SCRIPT_CONTENT =
<<~JAVASCRIPT (content, type) => { if (type === undefined) type = 'text/javascript'; const script = document.createElement('script'); script.type = type; script.text = content; let error = null; script.onerror = e => error = e; document.head.appendChild(script); if (error) throw error; return script; } JAVASCRIPT
- ADD_STYLE_URL =
<<~JAVASCRIPT async (url) => { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = url; const promise = new Promise((res, rej) => { link.onload = res; link.onerror = rej; }); document.head.appendChild(link); await promise; return link; } JAVASCRIPT
- ADD_STYLE_CONTENT =
<<~JAVASCRIPT async (content) => { const style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(content)); const promise = new Promise((res, rej) => { style.onload = res; style.onerror = rej; }); document.head.appendChild(style); await promise; return style; } JAVASCRIPT
Instance Attribute Summary collapse
-
#frame ⇒ Object
readonly
Returns the value of attribute frame.
Instance Method Summary collapse
- #add_binding_to_context(context, binding_function) ⇒ Object
- #add_script_tag(url: nil, path: nil, content: nil, type: nil) ⇒ Object
- #add_style_tag(url: nil, path: nil, content: nil) ⇒ Object
- #click(selector, delay: nil, button: nil, click_count: nil) ⇒ Object
- #content ⇒ String
- #context=(context) ⇒ Object
- #delete_context(execution_context_id) ⇒ Object
- #detach ⇒ Object
-
#eval_on_selector(selector, page_function, *args) ⇒ !Promise<(!Object|undefined)>
(also: #Seval)
`$eval()` in JavaScript.
-
#eval_on_selector_all(selector, page_function, *args) ⇒ !Promise<(!Object|undefined)>
(also: #SSeval)
`$$eval()` in JavaScript.
- #evaluate(page_function, *args) ⇒ !Promise<*>
- #evaluate_handle(page_function, *args) ⇒ !Promise<!Puppeteer.JSHandle>
- #execution_context ⇒ !Promise<!Puppeteer.ExecutionContext>
- #focus(selector) ⇒ Object
- #has_context? ⇒ Boolean
-
#initialize(frame_manager, frame, timeout_settings) ⇒ DOMWorld
constructor
A new instance of DOMWorld.
-
#query_selector(selector) ⇒ !Promise<?Puppeteer.ElementHandle>
(also: #S)
`$()` in JavaScript.
-
#query_selector_all(selector) ⇒ !Promise<!Array<!Puppeteer.ElementHandle>>
(also: #SS)
`$$()` in JavaScript.
- #select(selector, *values) ⇒ Array<String>
- #set_content(html, timeout: nil, wait_until: nil) ⇒ Object
-
#Sx(expression) ⇒ !Promise<!Array<!Puppeteer.ElementHandle>>
`$x()` in JavaScript.
- #tap(selector) ⇒ Object
- #title ⇒ String
- #type_text(selector, text, delay: nil) ⇒ Object
- #wait_for_function(page_function, args: [], polling: nil, timeout: nil) ⇒ Puppeteer::JSHandle
- #wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil) ⇒ Object
- #wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil) ⇒ Object
Constructor Details
#initialize(frame_manager, frame, timeout_settings) ⇒ DOMWorld
Returns a new instance of DOMWorld.
51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/puppeteer/dom_world.rb', line 51 def initialize(frame_manager, frame, timeout_settings) @frame_manager = frame_manager @frame = frame @timeout_settings = timeout_settings @context_promise = resolvable_future @wait_tasks = Set.new @bound_functions = {} @ctx_bindings = Set.new @detached = false frame_manager.client.on_event('Runtime.bindingCalled', &method(:handle_binding_called)) end |
Instance Attribute Details
#frame ⇒ Object (readonly)
Returns the value of attribute frame.
64 65 66 |
# File 'lib/puppeteer/dom_world.rb', line 64 def frame @frame end |
Instance Method Details
#add_binding_to_context(context, binding_function) ⇒ Object
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 |
# File 'lib/puppeteer/dom_world.rb', line 429 def add_binding_to_context(context, binding_function) return if @ctx_bindings.include?(binding_identifier(binding_function.name, context)) expression = binding_function.page_binding_init_string begin context.client.('Runtime.addBinding', name: binding_function.name, executionContextName: context.send(:_context_name)) context.evaluate(expression, 'internal', binding_function.name) rescue => err # We could have tried to evaluate in a context which was already # destroyed. This happens, for example, if the page is navigated while # we are trying to add the binding allowed = [ 'Execution context was destroyed', 'Cannot find context with specified id', ] if allowed.any? { |msg| err..include?(msg) } # ignore else raise end end @ctx_bindings << binding_identifier(binding_function.name, context) end |
#add_script_tag(url: nil, path: nil, content: nil, type: nil) ⇒ Object
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/puppeteer/dom_world.rb', line 237 def add_script_tag(url: nil, path: nil, content: nil, type: nil) if url begin return execution_context. evaluate_handle(ADD_SCRIPT_URL, url, type || ''). as_element rescue Puppeteer::ExecutionContext::EvaluationError # for Chrome raise "Loading script from #{url} failed" rescue Puppeteer::Connection::ProtocolError # for Firefox raise "Loading script from #{url} failed" end end if path contents = File.read(path) contents += "//# sourceURL=#{path.gsub(/\n/, '')}" return execution_context. evaluate_handle(ADD_SCRIPT_CONTENT, contents, type || ''). as_element end if content return execution_context. evaluate_handle(ADD_SCRIPT_CONTENT, content, type || ''). as_element end raise ArgumentError.new('Provide an object with a `url`, `path` or `content` property') end |
#add_style_tag(url: nil, path: nil, content: nil) ⇒ Object
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/puppeteer/dom_world.rb', line 301 def add_style_tag(url: nil, path: nil, content: nil) if url begin return execution_context.evaluate_handle(ADD_STYLE_URL, url).as_element rescue Puppeteer::ExecutionContext::EvaluationError # for Chrome raise "Loading style from #{url} failed" rescue Puppeteer::Connection::ProtocolError # for Firefox raise "Loading style from #{url} failed" end end if path contents = File.read(path) contents += "/*# sourceURL=#{path.gsub(/\n/, '')}*/" return execution_context.evaluate_handle(ADD_STYLE_CONTENT, contents).as_element end if content return execution_context.evaluate_handle(ADD_STYLE_CONTENT, content).as_element end raise ArgumentError.new('Provide an object with a `url`, `path` or `content` property') end |
#click(selector, delay: nil, button: nil, click_count: nil) ⇒ Object
365 366 367 368 369 |
# File 'lib/puppeteer/dom_world.rb', line 365 def click(selector, delay: nil, button: nil, click_count: nil) handle = query_selector(selector) or raise ElementNotFoundError.new(selector) handle.click(delay: delay, button: , click_count: click_count) handle.dispose end |
#content ⇒ String
191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/puppeteer/dom_world.rb', line 191 def content evaluate(<<-JAVASCRIPT) () => { let retVal = ''; if (document.doctype) retVal = new XMLSerializer().serializeToString(document.doctype); if (document.documentElement) retVal += document.documentElement.outerHTML; return retVal; } JAVASCRIPT end |
#context=(context) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/puppeteer/dom_world.rb', line 77 def context=(context) if context @ctx_bindings.clear unless @context_promise.resolved? @context_promise.fulfill(context) end @wait_tasks.each(&:async_rerun) else raise ArgumentError.new("context should now be nil. Use #delete_context for clearing document.") end end |
#delete_context(execution_context_id) ⇒ Object
89 90 91 92 |
# File 'lib/puppeteer/dom_world.rb', line 89 def delete_context(execution_context_id) @document = nil @context_promise = resolvable_future end |
#detach ⇒ Object
98 99 100 101 102 103 |
# File 'lib/puppeteer/dom_world.rb', line 98 def detach @detached = true @wait_tasks.each do |wait_task| wait_task.terminate(Puppeteer::WaitTask::TerminatedError.new('waitForFunction failed: frame got detached.')) end end |
#eval_on_selector(selector, page_function, *args) ⇒ !Promise<(!Object|undefined)> Also known as: Seval
`$eval()` in JavaScript.
167 168 169 |
# File 'lib/puppeteer/dom_world.rb', line 167 def eval_on_selector(selector, page_function, *args) document.eval_on_selector(selector, page_function, *args) end |
#eval_on_selector_all(selector, page_function, *args) ⇒ !Promise<(!Object|undefined)> Also known as: SSeval
`$$eval()` in JavaScript.
177 178 179 |
# File 'lib/puppeteer/dom_world.rb', line 177 def eval_on_selector_all(selector, page_function, *args) document.eval_on_selector_all(selector, page_function, *args) end |
#evaluate(page_function, *args) ⇒ !Promise<*>
125 126 127 |
# File 'lib/puppeteer/dom_world.rb', line 125 def evaluate(page_function, *args) execution_context.evaluate(page_function, *args) end |
#evaluate_handle(page_function, *args) ⇒ !Promise<!Puppeteer.JSHandle>
118 119 120 |
# File 'lib/puppeteer/dom_world.rb', line 118 def evaluate_handle(page_function, *args) execution_context.evaluate_handle(page_function, *args) end |
#execution_context ⇒ !Promise<!Puppeteer.ExecutionContext>
108 109 110 111 112 113 |
# File 'lib/puppeteer/dom_world.rb', line 108 def execution_context if @detached raise DetachedError.new("Execution Context is not available in detached frame \"#{@frame.url}\" (are you trying to evaluate?)") end @context_promise.value! end |
#focus(selector) ⇒ Object
372 373 374 375 376 |
# File 'lib/puppeteer/dom_world.rb', line 372 def focus(selector) handle = query_selector(selector) or raise ElementNotFoundError.new(selector) handle.focus handle.dispose end |
#has_context? ⇒ Boolean
94 95 96 |
# File 'lib/puppeteer/dom_world.rb', line 94 def has_context? @context_promise.resolved? end |
#query_selector(selector) ⇒ !Promise<?Puppeteer.ElementHandle> Also known as: S
`$()` in JavaScript.
132 133 134 |
# File 'lib/puppeteer/dom_world.rb', line 132 def query_selector(selector) document.query_selector(selector) end |
#query_selector_all(selector) ⇒ !Promise<!Array<!Puppeteer.ElementHandle>> Also known as: SS
`$$()` in JavaScript.
185 186 187 |
# File 'lib/puppeteer/dom_world.rb', line 185 def query_selector_all(selector) document.query_selector_all(selector) end |
#select(selector, *values) ⇒ Array<String>
390 391 392 393 394 395 396 |
# File 'lib/puppeteer/dom_world.rb', line 390 def select(selector, *values) handle = query_selector(selector) or raise ElementNotFoundError.new(selector) result = handle.select(*values) handle.dispose result end |
#set_content(html, timeout: nil, wait_until: nil) ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/puppeteer/dom_world.rb', line 207 def set_content(html, timeout: nil, wait_until: nil) option_wait_until = [wait_until || 'load'].flatten option_timeout = timeout || @timeout_settings. # We rely upon the fact that document.open() will reset frame lifecycle with "init" # lifecycle event. @see https://crrev.com/608658 js = <<-JAVASCRIPT (html) => { document.open(); document.write(html); document.close(); } JAVASCRIPT evaluate(js, html) watcher = Puppeteer::LifecycleWatcher.new(@frame_manager, @frame, option_wait_until, option_timeout) begin await_any( watcher.timeout_or_termination_promise, watcher.lifecycle_promise, ) ensure watcher.dispose end end |
#Sx(expression) ⇒ !Promise<!Array<!Puppeteer.ElementHandle>>
`$x()` in JavaScript. $ is not allowed to use as a method name in Ruby.
158 159 160 |
# File 'lib/puppeteer/dom_world.rb', line 158 def Sx(expression) document.Sx(expression) end |
#tap(selector) ⇒ Object
399 400 401 402 403 |
# File 'lib/puppeteer/dom_world.rb', line 399 def tap(selector) handle = query_selector(selector) or raise ElementNotFoundError.new(selector) handle.tap handle.dispose end |
#title ⇒ String
597 598 599 |
# File 'lib/puppeteer/dom_world.rb', line 597 def title evaluate('() => document.title') end |
#type_text(selector, text, delay: nil) ⇒ Object
408 409 410 411 412 |
# File 'lib/puppeteer/dom_world.rb', line 408 def type_text(selector, text, delay: nil) handle = query_selector(selector) or raise ElementNotFoundError.new(selector) handle.type_text(text, delay: delay) handle.dispose end |
#wait_for_function(page_function, args: [], polling: nil, timeout: nil) ⇒ Puppeteer::JSHandle
581 582 583 584 585 586 587 588 589 590 591 592 593 |
# File 'lib/puppeteer/dom_world.rb', line 581 def wait_for_function(page_function, args: [], polling: nil, timeout: nil) option_polling = polling || 'raf' option_timeout = timeout || @timeout_settings.timeout Puppeteer::WaitTask.new( dom_world: self, predicate_body: page_function, title: 'function', polling: option_polling, timeout: option_timeout, args: args, ).await_promise end |
#wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil) ⇒ Object
418 419 420 421 422 |
# File 'lib/puppeteer/dom_world.rb', line 418 def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil) # call wait_for_selector_in_page with custom query selector. query_selector_manager = Puppeteer::QueryHandlerManager.instance query_selector_manager.detect_query_handler(selector).wait_for(self, visible: visible, hidden: hidden, timeout: timeout) end |
#wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil) ⇒ Object
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
# File 'lib/puppeteer/dom_world.rb', line 539 def wait_for_xpath(xpath, visible: nil, hidden: nil, timeout: nil) option_wait_for_visible = visible || false option_wait_for_hidden = hidden || false option_timeout = timeout || @timeout_settings.timeout polling = if option_wait_for_visible || option_wait_for_hidden 'raf' else 'mutation' end title = "XPath #{xpath}#{option_wait_for_hidden ? 'to be hidden' : ''}" xpath_predicate = make_predicate_string( predicate_arg_def: '(selector, waitForVisible, waitForHidden)', predicate_body: <<~JAVASCRIPT const node = document.evaluate(selector, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; return checkWaitForOptions(node, waitForVisible, waitForHidden); JAVASCRIPT ) wait_task = Puppeteer::WaitTask.new( dom_world: self, predicate_body: xpath_predicate, title: title, polling: polling, timeout: option_timeout, args: [xpath, option_wait_for_visible, option_wait_for_hidden], ) handle = wait_task.await_promise unless handle.as_element handle.dispose return nil end handle.as_element end |