Skip to content

Commit

Permalink
Allow setting of optional cookie attributes (#711)
Browse files Browse the repository at this point in the history
Add a `set_cookie/4` function to permit the setting of optional cookie
attributes per the [WebDriver
specification](https://www.w3.org/TR/webdriver1/#cookies).
  • Loading branch information
merhard authored Oct 4, 2022
1 parent 8d86c26 commit f779aee
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 10 deletions.
38 changes: 37 additions & 1 deletion integration_test/cases/browser/cookies_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ defmodule Wallaby.Integration.Browser.CookiesTest do
session
|> visit("/")
|> Browser.set_cookie("api_token", "abc123")
|> visit("/")
|> visit("/index.html")
|> Browser.cookies()
|> hd()

assert cookie["name"] == "api_token"
assert cookie["value"] == "abc123"
assert cookie["path"] == "/"
assert cookie["secure"] == false
assert cookie["httpOnly"] == false
end

test "without visiting a page first throws an error", %{session: session} do
Expand All @@ -35,4 +38,37 @@ defmodule Wallaby.Integration.Browser.CookiesTest do
end
end
end

describe "set_cookie/4" do
test "sets a cookie in the browser", %{session: session} do
expiry = DateTime.utc_now() |> DateTime.to_unix() |> Kernel.+(1000)

cookie =
session
|> visit("/")
|> Browser.set_cookie("api_token", "abc123",
path: "/index.html",
secure: true,
httpOnly: true,
expiry: expiry
)
|> visit("/index.html")
|> Browser.cookies()
|> hd()

assert cookie["name"] == "api_token"
assert cookie["value"] == "abc123"
assert cookie["path"] == "/index.html"
assert cookie["secure"] == true
assert cookie["httpOnly"] == true
assert cookie["expiry"] == expiry
end

test "without visiting a page first throws an error", %{session: session} do
assert_raise CookieError, fn ->
session
|> Browser.set_cookie("other_cookie", "test", secure: true, httpOnly: true)
end
end
end
end
4 changes: 2 additions & 2 deletions lib/wallaby/browser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1281,12 +1281,12 @@ defmodule Wallaby.Browser do
cookies_list
end

def set_cookie(%Session{driver: driver} = session, key, value) do
def set_cookie(%Session{driver: driver} = session, key, value, attributes \\ []) do
if blank_page?(session) do
raise CookieError
end

case driver.set_cookie(session, key, value) do
case driver.set_cookie(session, key, value, attributes) do
{:ok, _list} ->
session

Expand Down
5 changes: 4 additions & 1 deletion lib/wallaby/chrome.ex
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,11 @@ defmodule Wallaby.Chrome do
def page_title(session), do: delegate(:page_title, session)
@doc false
def page_source(session), do: delegate(:page_source, session)

@doc false
def set_cookie(session, key, value), do: delegate(:set_cookie, session, [key, value])
def set_cookie(session, key, value, attributes \\ []),
do: delegate(:set_cookie, session, [key, value, attributes])

@doc false
def visit(session, url), do: delegate(:visit, session, [url])
@doc false
Expand Down
2 changes: 2 additions & 0 deletions lib/wallaby/driver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ defmodule Wallaby.Driver do
Invoked to set a cookie on a session
"""
@callback set_cookie(Session.t(), String.t(), String.t()) :: {:ok, any} | {:error, reason}
@callback set_cookie(Session.t(), String.t(), String.t(), keyword()) ::
{:ok, any} | {:error, reason}

@doc """
Invoked to set the size of the currently focused window.
Expand Down
2 changes: 1 addition & 1 deletion lib/wallaby/exceptions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ defmodule Wallaby.CookieError do
You're most likely seeing this error because you're trying to set a cookie before
you have visited a page. You can fix this issue by calling `visit/1`
before you call `set_cookie/3`.
before you call `set_cookie/3` or `set_cookie/4`.
"""

%__MODULE__{message: msg}
Expand Down
4 changes: 2 additions & 2 deletions lib/wallaby/selenium.ex
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ defmodule Wallaby.Selenium do
end

@doc false
def set_cookie(%Session{} = session, key, value) do
WebdriverClient.set_cookie(session, key, value)
def set_cookie(%Session{} = session, key, value, attributes \\ []) do
WebdriverClient.set_cookie(session, key, value, attributes)
end

@doc false
Expand Down
20 changes: 17 additions & 3 deletions lib/wallaby/webdriver_client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,26 @@ defmodule Wallaby.WebdriverClient do

@doc """
Sets a cookie for the session.
It accepts a list of optional cookie attributes per the
[WebDriver specification](https://www.w3.org/TR/webdriver1/#cookies):
* path (string)
* domain (string)
* secure (boolean)
* httpOnly (boolean)
* expiry (integer; number of seconds since Unix Epoch)
"""
@spec set_cookie(Session.t(), String.t(), String.t()) :: {:ok, []}
def set_cookie(session, key, value) do
params = %{cookie: %{name: key, value: value}}
@spec set_cookie(Session.t(), String.t(), String.t(), keyword()) :: {:ok, []}
def set_cookie(session, key, value, attributes \\ []) do
cookie_params =
attributes
|> Enum.into(%{})
|> Map.take(~w[path domain secure httpOnly expiry]a)
|> Map.merge(%{name: key, value: value})

with {:ok, resp} <- request(:post, "#{session.url}/cookie", params) do
with {:ok, resp} <- request(:post, "#{session.url}/cookie", %{cookie: cookie_params}) do
Map.fetch(resp, "value")
end
end
Expand Down
40 changes: 40 additions & 0 deletions test/wallaby/selenium/webdriver_client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,46 @@ defmodule Wallaby.WebdriverClientTest do
end
end

describe "set_cookie/4" do
test "sends the correct request to the server", %{bypass: bypass} do
session = build_session_for_bypass(bypass)
key = "tester"
value = "McTestington"
expiry = DateTime.utc_now() |> DateTime.to_unix() |> Kernel.+(1000)

Bypass.expect(bypass, "POST", "/session/#{session.id}/cookie", fn conn ->
conn = parse_body(conn)

assert conn.body_params == %{
"cookie" => %{
"name" => key,
"value" => value,
"path" => "/index.html",
"domain" => "example.com",
"secure" => true,
"httpOnly" => true,
"expiry" => expiry
}
}

send_json_resp(conn, 200, %{
"sessionId" => session.id,
"status" => 0,
"value" => []
})
end)

assert {:ok, []} =
Client.set_cookie(session, key, value,
path: "/index.html",
domain: "example.com",
secure: true,
httpOnly: true,
expiry: expiry
)
end
end

describe "set_window_size/3" do
test "sends the correct request to the server", %{bypass: bypass} do
session = build_session_for_bypass(bypass)
Expand Down

0 comments on commit f779aee

Please sign in to comment.