YusukeIwaki / playwright-ruby-client

Playwright client for Ruby
https://playwright-ruby-client.vercel.app/
MIT License
343 stars 36 forks source link

NoMethodError when enabling on_save_trace with Playwright in server mode for Rails System Test #307

Open mizoR opened 2 months ago

mizoR commented 2 months ago

Hi there, thanks for this great gem—it's been really helpful!

Usecase / What to achieve

I am running system tests for a Rails application using Playwright in server mode. I want to enable on_save_trace to collect tracing information for debugging and performance analysis.

Question

I'm using Playwright in server mode to run System tests in a Rails environment. When I enable on_save_trace, I encounter the following error:

/usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/connection.rb:113:in `block in async_send_message_to_server': undefined method `add_stack_to_tracing_no_reply' for nil (NoMethodError)

          @local_utils.add_stack_to_tracing_no_reply(id, frames)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/connection.rb:133:in `with_generated_id'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/connection.rb:80:in `async_send_message_to_server'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/connection.rb:121:in `send_message_to_server'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/channel.rb:35:in `block in send_message_to_server_result'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/channel.rb:67:in `with_logging'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/channel.rb:34:in `send_message_to_server_result'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/channel.rb:20:in `send_message_to_server'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright/channel_owners/browser.rb:75:in `close'
        from /usr/local/bundle/gems/playwright-ruby-client-1.47.0/lib/playwright_api/browser.rb:37:in `close'
        from /usr/local/bundle/gems/capybara-playwright-driver-0.5.2/lib/capybara/playwright/driver.rb:56:in `quit'
        from /usr/local/bundle/gems/capybara-playwright-driver-0.5.2/lib/capybara/playwright/driver.rb:48:in `block in create_playwright_browser'
/usr/local/bundle/gems/rspec-core-3.13.1/lib/rspec/core/runner.rb:46:in `exit': exit (SystemExit)
        from /usr/local/bundle/gems/rspec-core-3.13.1/lib/rspec/core/runner.rb:46:in `invoke'
        from /usr/local/bundle/gems/rspec-core-3.13.1/exe/rspec:4:in `<top (required)>'
        from bin/rspec:27:in `load'
        from bin/rspec:27:in `<main>'

Here is a Rails application that reproduces the problem. https://github.com/mizoR/capybara-playwright-example

I'm not sure if on_save_trace is fully supported in server mode or if this is a bug. Could someone clarify if this functionality is expected to work in server mode, or if there might be a missing configuration or an alternative approach?

Thank you for your support and for all your hard work on Playwright.

YusukeIwaki commented 2 months ago

It seems LocalUtils is available only when playwright driver is executed on the local.

Playwright server-mode is not officially used in Python, Java, C# drivers. (ref: https://github.com/microsoft/playwright/issues/4687, https://github.com/microsoft/playwright-python/issues/732 ) They use BrowserType#connect instead and BrowserType internally has local driver connection.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    # browser = p.chromium.launch(channel="chrome")
    browser = p.chromium.connect('ws://localhost:9999/chromium')
    try:
        context = browser.new_context()
        context.tracing.start(screenshots=True, snapshots=True)
        page = context.new_page()
        page.goto("https://github.com/YusukeIwaki")
        page.screenshot(path="YusukeIwaki.png")
        context.tracing.stop(path="trace.zip")
    finally:
        browser.close()

On the other hand, Ruby driver does not use BrowserType for connecting to the Playwright server or Browser server. This is the root cause of this issue...

#Playwright.create(playwright_cli_executable_path: './node_modules/.bin/playwright') do |playwright|
Playwright.connect_to_browser_server('ws://localhost:9999/chromium') do |browser|
  # playwright.chromium.launch(headless: false) do |browser|
    context = browser.new_context
    context.tracing.start(screenshots: true, snapshots: true)
    page = context.new_page
    page.goto('https://github.com/YusukeIwaki')
    page.screenshot(path: './YusukeIwaki.png')
    context.tracing.stop(path: './trace.zip')
    context.close
  # end
end

The event for creating LocalUtils are not notified via WebSocket on connecting to the browser server nor Playwright server...

SEND>{:id=>1, :guid=>"", :method=>"initialize", :params=>{:sdkLanguage=>"python"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Browser", "initializer"=>{"version"=>"129.0.6668.29", "name"=>"chromium"}, "guid"=>"browser@95b031dd7dfcff5de37884f28d607870"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Android", "initializer"=>{}, "guid"=>"android@ed18adde7575ca2794b8ec7a9a65e71e"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"/Users/yusuke-iwaki/Library/Caches/ms-playwright/chromium-1134/chrome-mac/Chromium.app/Contents/MacOS/Chromium", "name"=>"chromium"}, "guid"=>"browser-type@8353c19428cd8090c49b92b0eaa6f38e"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"", "name"=>"bidi"}, "guid"=>"browser-type@d940a52b71820e7a34e3b198f6cb5149"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"/Users/yusuke-iwaki/Library/Caches/ms-playwright/firefox-1463/firefox/Nightly.app/Contents/MacOS/firefox", "name"=>"firefox"}, "guid"=>"browser-type@7cda8cd2d79ab5248b49d3a6a41abc13"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"/Users/yusuke-iwaki/Library/Caches/ms-playwright/webkit-2070/pw_run.sh", "name"=>"webkit"}, "guid"=>"browser-type@63d5a5d9309756acfca71abed28e10a5"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Electron", "initializer"=>{}, "guid"=>"electron@e9bcc4891477eda36f7ae8df5cc039b1"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Selectors", "initializer"=>{}, "guid"=>"selectors@aa743242cb8c7f20ff15d7e27944231a"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Playwright", "initializer"=>{"chromium"=>{"guid"=>"browser-type@8353c19428cd8090c49b92b0eaa6f38e"}, "bidi"=>{"guid"=>"browser-type@d940a52b71820e7a34e3b198f6cb5149"}, "firefox"=>{"guid"=>"browser-type@7cda8cd2d79ab5248b49d3a6a41abc13"}, "webkit"=>{"guid"=>"browser-type@63d5a5d9309756acfca71abed28e10a5"}, "android"=>{"guid"=>"android@ed18adde7575ca2794b8ec7a9a65e71e"}, "electron"=>{"guid"=>"electron@e9bcc4891477eda36f7ae8df5cc039b1"}, "selectors"=>{"guid"=>"selectors@aa743242cb8c7f20ff15d7e27944231a"}, "preLaunchedBrowser"=>{"guid"=>"browser@95b031dd7dfcff5de37884f28d607870"}}, "guid"=>"Playwright"}}
SEND>{:id=>1, :guid=>"", :method=>"initialize", :params=>{:sdkLanguage=>"python"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Browser", "initializer"=>{"version"=>"129.0.6668.29", "name"=>"chromium"}, "guid"=>"browser@3c30d3c43ecf37109981deb9caf5ce5d"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Android", "initializer"=>{}, "guid"=>"android@741e8a6166c27961e20160c7aca957a9"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"/Users/yusuke-iwaki/Library/Caches/ms-playwright/chromium-1134/chrome-mac/Chromium.app/Contents/MacOS/Chromium", "name"=>"chromium"}, "guid"=>"browser-type@a74ac7bbbf7937fdc2175865dc516f83"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"", "name"=>"bidi"}, "guid"=>"browser-type@6df0ab37554b3c36b4783c69deb030ec"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"/Users/yusuke-iwaki/Library/Caches/ms-playwright/firefox-1463/firefox/Nightly.app/Contents/MacOS/firefox", "name"=>"firefox"}, "guid"=>"browser-type@d25715cf2d33b1f243c7436e191d9419"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"BrowserType", "initializer"=>{"executablePath"=>"/Users/yusuke-iwaki/Library/Caches/ms-playwright/webkit-2070/pw_run.sh", "name"=>"webkit"}, "guid"=>"browser-type@b9720532df1aefd62bc67041e5aec6fc"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Electron", "initializer"=>{}, "guid"=>"electron@aebfea77d367580c1e8a54e10c3c1ede"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Selectors", "initializer"=>{}, "guid"=>"selectors@40c079f12c623f09faddd3e58639df3a"}}
RECV>{"guid"=>"", "method"=>"__create__", "params"=>{"type"=>"Playwright", "initializer"=>{"chromium"=>{"guid"=>"browser-type@a74ac7bbbf7937fdc2175865dc516f83"}, "bidi"=>{"guid"=>"browser-type@6df0ab37554b3c36b4783c69deb030ec"}, "firefox"=>{"guid"=>"browser-type@d25715cf2d33b1f243c7436e191d9419"}, "webkit"=>{"guid"=>"browser-type@b9720532df1aefd62bc67041e5aec6fc"}, "android"=>{"guid"=>"android@741e8a6166c27961e20160c7aca957a9"}, "electron"=>{"guid"=>"electron@aebfea77d367580c1e8a54e10c3c1ede"}, "selectors"=>{"guid"=>"selectors@40c079f12c623f09faddd3e58639df3a"}, "preLaunchedBrowser"=>{"guid"=>"browser@3c30d3c43ecf37109981deb9caf5ce5d"}}, "guid"=>"Playwright"}}
mizoR commented 2 months ago

Thank you for your explanation!

From your response, I understand that LocalUtils is only available when the Playwright driver is run locally, and that server mode is not officially supported for the Python, Java, and C# drivers. This probably means that it might also be difficult to fully support Ruby drivers in server mode, right?

I was hoping to avoid installing Playwright in the application container, but given the current limitations, if tracing is important, I might need to consider switching to a local connection instead of using the server mode.

Thanks again for your support and the helpful information! ✨