-
Notifications
You must be signed in to change notification settings - Fork 936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: add cookie tests #142
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,387 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import asyncio | ||
import datetime | ||
|
||
import pytest | ||
|
||
from playwright import Error | ||
|
||
|
||
async def test_should_work(context, page, server): | ||
await page.goto(server.EMPTY_PAGE) | ||
await context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "password", "value": "123456"}] | ||
) | ||
assert await page.evaluate("() => document.cookie") == "password=123456" | ||
|
||
|
||
async def test_should_roundtrip_cookie(context, page, server): | ||
await page.goto(server.EMPTY_PAGE) | ||
# @see https://en.wikipedia.org/wiki/Year_2038_problem | ||
date = int(datetime.datetime(2038, 1, 1).timestamp() * 1000) | ||
document_cookie = await page.evaluate( | ||
"""timestamp => { | ||
const date = new Date(timestamp); | ||
document.cookie = `username=John Doe;expires=${date.toUTCString()}`; | ||
return document.cookie; | ||
}""", | ||
date, | ||
) | ||
assert document_cookie == "username=John Doe" | ||
cookies = await context.cookies() | ||
await context.clearCookies() | ||
assert await context.cookies() == [] | ||
await context.addCookies(cookies) | ||
assert await context.cookies() == cookies | ||
|
||
|
||
async def test_should_send_cookie_header(server, context): | ||
cookie = [] | ||
|
||
def handler(request): | ||
cookie.extend(request.requestHeaders.getRawHeaders("cookie")) | ||
request.finish() | ||
|
||
server.set_route("/empty.html", handler) | ||
await context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "cookie", "value": "value"}] | ||
) | ||
page = await context.newPage() | ||
await page.goto(server.EMPTY_PAGE) | ||
assert cookie == ["cookie=value"] | ||
|
||
|
||
async def test_should_isolate_cookies_in_browser_contexts(context, server, browser): | ||
another_context = await browser.newContext() | ||
await context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "isolatecookie", "value": "page1value"}] | ||
) | ||
await another_context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "isolatecookie", "value": "page2value"}] | ||
) | ||
|
||
cookies_1 = await context.cookies() | ||
cookies_2 = await another_context.cookies() | ||
assert len(cookies_1) == 1 | ||
assert len(cookies_2) == 1 | ||
assert cookies_1[0]["name"] == "isolatecookie" | ||
assert cookies_1[0]["value"] == "page1value" | ||
assert cookies_2[0]["name"] == "isolatecookie" | ||
assert cookies_2[0]["value"] == "page2value" | ||
await another_context.close() | ||
|
||
|
||
async def test_should_isolate_session_cookies(context, server, browser): | ||
server.set_route( | ||
"/setcookie.html", | ||
lambda r: (r.setHeader("Set-Cookie", "session=value"), r.finish(),), | ||
) | ||
|
||
page_1 = await context.newPage() | ||
await page_1.goto(server.PREFIX + "/setcookie.html") | ||
## | ||
page_2 = await context.newPage() | ||
await page_2.goto(server.EMPTY_PAGE) | ||
cookies_2 = await context.cookies() | ||
assert len(cookies_2) == 1 | ||
assert ",".join(list(map(lambda c: c["value"], cookies_2))) == "value" | ||
## | ||
context_b = await browser.newContext() | ||
page_3 = await context_b.newPage() | ||
await page_3.goto(server.EMPTY_PAGE) | ||
cookies_3 = await context_b.cookies() | ||
assert cookies_3 == [] | ||
await context_b.close() | ||
Comment on lines
+93
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The javascript version used scoping; I've manually appended subscripts to (hopefully) achieve the same thing. The few tests with |
||
|
||
|
||
async def test_should_isolate_persistent_cookies(context, server, browser): | ||
server.set_route( | ||
"/setcookie.html", | ||
lambda r: ( | ||
r.setHeader("Set-Cookie", "persistent=persistent-value; max-age=3600"), | ||
r.finish(), | ||
), | ||
) | ||
|
||
page = await context.newPage() | ||
await page.goto(server.PREFIX + "/setcookie.html") | ||
|
||
context_1 = context | ||
context_2 = await browser.newContext() | ||
[page_1, page_2] = await asyncio.gather(context_1.newPage(), context_2.newPage()) | ||
await asyncio.gather(page_1.goto(server.EMPTY_PAGE), page_2.goto(server.EMPTY_PAGE)) | ||
[cookies_1, cookies_2] = await asyncio.gather( | ||
context_1.cookies(), context_2.cookies() | ||
) | ||
assert len(cookies_1) == 1 | ||
assert cookies_1[0]["name"] == "persistent" | ||
assert cookies_1[0]["value"] == "persistent-value" | ||
assert len(cookies_2) == 0 | ||
await context_2.close() | ||
|
||
|
||
async def test_should_isolate_send_cookie_header(server, context, browser): | ||
cookie = [] | ||
|
||
def handler(request): | ||
cookie.extend(request.requestHeaders.getRawHeaders("cookie") or []) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the JS version, cookie was simply assigned to. In Python, that didn't work so I used a mutable list. |
||
request.finish() | ||
|
||
server.set_route("/empty.html", handler) | ||
|
||
await context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "sendcookie", "value": "value"}] | ||
) | ||
|
||
page_1 = await context.newPage() | ||
await page_1.goto(server.EMPTY_PAGE) | ||
assert cookie == ["sendcookie=value"] | ||
cookie.clear() | ||
## | ||
context_2 = await browser.newContext() | ||
page_2 = await context_2.newPage() | ||
await page_2.goto(server.EMPTY_PAGE) | ||
assert cookie == [] | ||
await context_2.close() | ||
|
||
|
||
async def test_should_isolate_cookies_between_launches(browser_factory, server): | ||
browser_1 = await browser_factory() | ||
context_1 = await browser_1.newContext() | ||
await context_1.addCookies( | ||
[ | ||
{ | ||
"url": server.EMPTY_PAGE, | ||
"name": "cookie-in-context-1", | ||
"value": "value", | ||
"expires": int(datetime.datetime.now().timestamp() + 10000), | ||
} | ||
] | ||
) | ||
await browser_1.close() | ||
|
||
browser_2 = await browser_factory() | ||
context_2 = await browser_2.newContext() | ||
cookies = await context_2.cookies() | ||
assert cookies == [] | ||
await browser_2.close() | ||
|
||
|
||
async def test_should_set_multiple_cookies(context, page, server): | ||
await page.goto(server.EMPTY_PAGE) | ||
await context.addCookies( | ||
[ | ||
{"url": server.EMPTY_PAGE, "name": "multiple-1", "value": "123456"}, | ||
{"url": server.EMPTY_PAGE, "name": "multiple-2", "value": "bar"}, | ||
] | ||
) | ||
assert ( | ||
await page.evaluate( | ||
"""() => { | ||
const cookies = document.cookie.split(';'); | ||
return cookies.map(cookie => cookie.trim()).sort(); | ||
}""" | ||
) | ||
== ["multiple-1=123456", "multiple-2=bar"] | ||
) | ||
|
||
|
||
async def test_should_have_expires_set_to_neg_1_for_session_cookies(context, server): | ||
await context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "expires", "value": "123456"}] | ||
) | ||
cookies = await context.cookies() | ||
assert cookies[0]["expires"] == -1 | ||
|
||
|
||
async def test_should_set_cookie_with_reasonable_defaults(context, server): | ||
await context.addCookies( | ||
[{"url": server.EMPTY_PAGE, "name": "defaults", "value": "123456"}] | ||
) | ||
cookies = await context.cookies() | ||
cookies.sort(key=lambda r: r["name"]) | ||
assert cookies == [ | ||
{ | ||
"name": "defaults", | ||
"value": "123456", | ||
"domain": "localhost", | ||
"path": "/", | ||
"expires": -1, | ||
"httpOnly": False, | ||
"secure": False, | ||
"sameSite": "None", | ||
} | ||
] | ||
|
||
|
||
async def test_should_set_a_cookie_with_a_path(context, page, server): | ||
await page.goto(server.PREFIX + "/grid.html") | ||
await context.addCookies( | ||
[ | ||
{ | ||
"domain": "localhost", | ||
"path": "/grid.html", | ||
"name": "gridcookie", | ||
"value": "GRID", | ||
} | ||
] | ||
) | ||
assert await context.cookies() == [ | ||
{ | ||
"name": "gridcookie", | ||
"value": "GRID", | ||
"domain": "localhost", | ||
"path": "/grid.html", | ||
"expires": -1, | ||
"httpOnly": False, | ||
"secure": False, | ||
"sameSite": "None", | ||
} | ||
] | ||
assert await page.evaluate("document.cookie") == "gridcookie=GRID" | ||
await page.goto(server.EMPTY_PAGE) | ||
assert await page.evaluate("document.cookie") == "" | ||
await page.goto(server.PREFIX + "/grid.html") | ||
assert await page.evaluate("document.cookie") == "gridcookie=GRID" | ||
|
||
|
||
async def test_should_not_set_a_cookie_with_blank_page_url(context, server): | ||
with pytest.raises(Error) as exc_info: | ||
await context.addCookies( | ||
[ | ||
{"url": server.EMPTY_PAGE, "name": "example-cookie", "value": "best"}, | ||
{"url": "about:blank", "name": "example-cookie-blank", "value": "best"}, | ||
] | ||
) | ||
assert ( | ||
'Blank page can not have cookie "example-cookie-blank"' | ||
in exc_info.value.message | ||
) | ||
|
||
|
||
async def test_should_not_set_a_cookie_on_a_data_url_page(context): | ||
with pytest.raises(Error) as exc_info: | ||
await context.addCookies( | ||
[ | ||
{ | ||
"url": "data:,Hello%2C%20World!", | ||
"name": "example-cookie", | ||
"value": "best", | ||
} | ||
] | ||
) | ||
assert ( | ||
'Data URL page can not have cookie "example-cookie"' in exc_info.value.message | ||
) | ||
|
||
|
||
async def test_should_default_to_setting_secure_cookie_for_https_websites( | ||
context, page, server | ||
): | ||
await page.goto(server.EMPTY_PAGE) | ||
SECURE_URL = "https://example.com" | ||
await context.addCookies([{"url": SECURE_URL, "name": "foo", "value": "bar"}]) | ||
[cookie] = await context.cookies(SECURE_URL) | ||
assert cookie["secure"] | ||
|
||
|
||
async def test_should_be_able_to_set_unsecure_cookie_for_http_website( | ||
context, page, server | ||
): | ||
await page.goto(server.EMPTY_PAGE) | ||
HTTP_URL = "http://example.com" | ||
await context.addCookies([{"url": HTTP_URL, "name": "foo", "value": "bar"}]) | ||
[cookie] = await context.cookies(HTTP_URL) | ||
assert not cookie["secure"] | ||
|
||
|
||
async def test_should_set_a_cookie_on_a_different_domain(context, page, server): | ||
await page.goto(server.EMPTY_PAGE) | ||
await context.addCookies( | ||
[{"url": "https://www.example.com", "name": "example-cookie", "value": "best"}] | ||
) | ||
assert await page.evaluate("document.cookie") == "" | ||
assert await context.cookies("https://www.example.com") == [ | ||
{ | ||
"name": "example-cookie", | ||
"value": "best", | ||
"domain": "www.example.com", | ||
"path": "/", | ||
"expires": -1, | ||
"httpOnly": False, | ||
"secure": True, | ||
"sameSite": "None", | ||
} | ||
] | ||
|
||
|
||
async def test_should_set_cookies_for_a_frame(context, page, server): | ||
await page.goto(server.EMPTY_PAGE) | ||
await context.addCookies( | ||
[{"url": server.PREFIX, "name": "frame-cookie", "value": "value"}] | ||
) | ||
await page.evaluate( | ||
"""src => { | ||
let fulfill; | ||
const promise = new Promise(x => fulfill = x); | ||
const iframe = document.createElement('iframe'); | ||
document.body.appendChild(iframe); | ||
iframe.onload = fulfill; | ||
iframe.src = src; | ||
return promise; | ||
}""", | ||
server.PREFIX + "/grid.html", | ||
) | ||
|
||
assert await page.frames[1].evaluate("document.cookie") == "frame-cookie=value" | ||
|
||
|
||
async def test_should_not_block_third_party_cookies( | ||
context, page, server, is_chromium, is_firefox | ||
): | ||
await page.goto(server.EMPTY_PAGE) | ||
await page.evaluate( | ||
"""src => { | ||
let fulfill; | ||
const promise = new Promise(x => fulfill = x); | ||
const iframe = document.createElement('iframe'); | ||
document.body.appendChild(iframe); | ||
iframe.onload = fulfill; | ||
iframe.src = src; | ||
return promise; | ||
}""", | ||
server.CROSS_PROCESS_PREFIX + "/grid.html", | ||
) | ||
await page.frames[1].evaluate("document.cookie = 'username=John Doe'") | ||
await page.waitForTimeout(2000) | ||
allows_third_party = is_chromium or is_firefox | ||
cookies = await context.cookies(server.CROSS_PROCESS_PREFIX + "/grid.html") | ||
|
||
if allows_third_party: | ||
assert cookies == [ | ||
{ | ||
"domain": "127.0.0.1", | ||
"expires": -1, | ||
"httpOnly": False, | ||
"name": "username", | ||
"path": "/", | ||
"sameSite": "None", | ||
"secure": False, | ||
"value": "John Doe", | ||
} | ||
] | ||
else: | ||
assert cookies == [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I manually checked this matches the date from the JS version, but someone should double check since dates are always fun!