Skip to content

Commit

Permalink
fix: make sure ElementHandle.waitForSelector is evaluated in the righ…
Browse files Browse the repository at this point in the history
…t context
  • Loading branch information
YusukeIwaki committed Jan 1, 2022
1 parent c0d8c44 commit 75c827f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 25 deletions.
8 changes: 5 additions & 3 deletions lib/puppeteer/aria_query_handler.rb
Expand Up @@ -36,19 +36,21 @@ def query_one(element, selector)
end
end

def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil)
def wait_for(dom_world, selector, visible: nil, hidden: nil, timeout: nil, root: nil)
# addHandlerToWorld
binding_function = Puppeteer::DOMWorld::BindingFunction.new(
name: 'ariaQuerySelector',
proc: -> (sel) { query_one(dom_world.send(:document), sel) },
proc: -> (sel) { query_one(root || dom_world.send(:document), sel) },
)
dom_world.send(:wait_for_selector_in_page,
'(_, selector) => globalThis.ariaQuerySelector(selector)',
selector,
visible: visible,
hidden: hidden,
timeout: timeout,
binding_function: binding_function)
binding_function: binding_function,
root: root,
)
end

def query_all(element, selector)
Expand Down
13 changes: 12 additions & 1 deletion lib/puppeteer/element_handle.rb
Expand Up @@ -58,7 +58,18 @@ def inspect
# (30 seconds). Pass `0` to disable timeout. The default value can be changed
# by using the {@link Page.setDefaultTimeout} method.
def wait_for_selector(selector, visible: nil, hidden: nil, timeout: nil)
@context.world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout, root: self)
frame = @context.frame

secondary_world = frame.secondary_world
adopted_root = secondary_world.execution_context.adopt_element_handle(self)
handle = secondary_world.wait_for_selector(selector, visible: visible, hidden: hidden, timeout: timeout, root: adopted_root)
adopted_root.dispose
return nil unless handle

main_world = frame.main_world
result = main_world.execution_context.adopt_element_handle(handle)
handle.dispose
result
end

define_async_method :async_wait_for_selector
Expand Down
26 changes: 8 additions & 18 deletions lib/puppeteer/wait_task.rb
Expand Up @@ -67,24 +67,14 @@ def rerun
return if @terminated || run_count != @run_count

begin
if @root
success = @root.evaluate_handle(
WAIT_FOR_PREDICATE_PAGE_FUNCTION,
@predicate_body,
@polling,
@timeout,
*@args,
)
else
success = context.evaluate_handle(
WAIT_FOR_PREDICATE_PAGE_FUNCTION,
nil,
@predicate_body,
@polling,
@timeout,
*@args,
)
end
success = context.evaluate_handle(
WAIT_FOR_PREDICATE_PAGE_FUNCTION,
@root,
@predicate_body,
@polling,
@timeout,
*@args,
)
rescue => err
error = err
end
Expand Down
19 changes: 16 additions & 3 deletions spec/integration/aria_query_handler_spec.rb
Expand Up @@ -93,6 +93,19 @@
Timeout.timeout(1) { page.wait_for_selector('aria/[role="button"]') }
end

it 'should return the element handle' do
page.evaluate(<<~JAVASCRIPT)
() => (document.body.innerHTML = `<div></div>`)
JAVASCRIPT
element = page.query_selector('div')
inner_element = element.wait_for_selector('aria/test') do
element.evaluate(<<~JAVASCRIPT)
el => el.innerHTML="<p><button>test</button></p>"
JAVASCRIPT
end
expect(inner_element.evaluate('el => el.outerHTML')).to eq('<button>test</button>')
end

it 'should persist query handler bindings across reloads' do
page.goto(server_empty_page)
page.evaluate(add_element, 'button')
Expand Down Expand Up @@ -372,9 +385,9 @@
# });

it 'should return the element handle' do
promise = page.async_wait_for_selector('aria/zombo')
page.content = "<div aria-label='zombo'>anything</div>"
result = await promise
result = page.wait_for_selector('aria/zombo') do
page.content = "<div aria-label='zombo'>anything</div>"
end
expect(result).to be_a(Puppeteer::ElementHandle)
expect(page.evaluate('(x) => x.textContent', result)).to eq('anything')
end
Expand Down

0 comments on commit 75c827f

Please sign in to comment.