YusukeIwaki / capybara-playwright-driver

Playwright driver for Capybara
MIT License
154 stars 13 forks source link

How do I write a cookie through capybara-playwright? #64

Closed mhenrixon closed 1 year ago

mhenrixon commented 1 year ago

Similar to here and the linked examples: https://world.hey.com/lewis/faster-rails-system-tests-f01df53b

I've been browsing through the code but it doesn't strike me as obvious how to achieve that.

YusukeIwaki commented 1 year ago

For using cookie, please try this.

with_playwright_page do |page|
  page.context.add_cookie(...)
end

Also please check this official article. https://playwright.dev/docs/auth For reducing login for each test case, storageState is useful with Playwright. This feature is also supported in this library, however I personally didn't try it...

mhenrixon commented 1 year ago

For completion, this is how I solved the problem:

  def fake_sign_in_as(user)
    session = user.sessions.create!
    # request    = ActionDispatch::Request.new(Rails.application.env_config)
    # cookie_jar = ActionDispatch::Cookies::CookieJar.new(request)
    cookie_jar = ActionDispatch::TestRequest.create.cookie_jar
    cookie_jar.signed.permanent[:session_token] = { value: session.id }

    page.driver.with_playwright_page do |page|
      page.context.add_cookies([
        { url: Capybara.app_host, name: "session_token", value: cookie_jar[:session_token] }
      ])
    end

    user
  end
dedman commented 8 months ago

I just tried this approach, but it doesn't seem to work unless a request has already been made. As far as I can tell with_playwright_page just returns nil if no visit request has been previously made. Which means that setting a cookie for auth purposes doesn't really work.

Does anyone know if there a way to have with_playwright_page work without making a request first?

mhenrixon commented 8 months ago

I think you are mistaken, @dedman. I use before hooks with RSpec literally everywhere.

CleanShot 2024-04-02 at 18 56 05@2x

Edit: pasted the wrong image :)

def using_app_domain(app = APP)
  return yield unless app

  app_host = "http://#{app}.lvh.me"
  original_host = Capybara.app_host
  Capybara.app_host = app_host
  yield
ensure
  Capybara.app_host = original_host
end

I believe you might not have the capybara host setup properly for it to work.