Skip to content

Commit 5580420

Browse files
authored
tests: added defaultbrowsercontext tests (#157)
1 parent 26ac810 commit 5580420

File tree

2 files changed

+379
-0
lines changed

2 files changed

+379
-0
lines changed

playwright/browser_type.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
locals_to_params,
3030
not_installed_error,
3131
)
32+
from playwright.network import serialize_headers
3233

3334

3435
class BrowserType(ChannelOwner):
@@ -134,6 +135,8 @@ async def launchPersistentContext(
134135
) -> BrowserContext:
135136
userDataDir = str(Path(userDataDir))
136137
params = locals_to_params(locals())
138+
if extraHTTPHeaders:
139+
params["extraHTTPHeaders"] = serialize_headers(extraHTTPHeaders)
137140
normalize_launch_params(params)
138141
try:
139142
return from_channel(
Lines changed: 376 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,376 @@
1+
# Copyright (c) Microsoft Corporation.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import asyncio
16+
import os
17+
18+
import pytest
19+
20+
from playwright.helper import Error
21+
22+
23+
@pytest.fixture()
24+
async def launch_persistent(tmpdir, launch_arguments, browser_type):
25+
context = None
26+
27+
async def _launch(**options):
28+
nonlocal context
29+
if context:
30+
raise ValueError("can only launch one persitent context")
31+
context = await browser_type.launchPersistentContext(
32+
str(tmpdir), **{**launch_arguments, **options}
33+
)
34+
return (context.pages[0], context)
35+
36+
yield _launch
37+
await context.close()
38+
39+
40+
async def test_context_cookies_should_work(server, launch_persistent):
41+
(page, context) = await launch_persistent()
42+
await page.goto(server.EMPTY_PAGE)
43+
document_cookie = await page.evaluate(
44+
"""() => {
45+
document.cookie = 'username=John Doe';
46+
return document.cookie;
47+
}"""
48+
)
49+
50+
assert document_cookie == "username=John Doe"
51+
assert await page.context.cookies() == [
52+
{
53+
"name": "username",
54+
"value": "John Doe",
55+
"domain": "localhost",
56+
"path": "/",
57+
"expires": -1,
58+
"httpOnly": False,
59+
"secure": False,
60+
"sameSite": "None",
61+
}
62+
]
63+
64+
65+
async def test_context_add_cookies_should_work(server, launch_persistent):
66+
(page, context) = await launch_persistent()
67+
await page.goto(server.EMPTY_PAGE)
68+
await page.context.addCookies(
69+
[{"url": server.EMPTY_PAGE, "name": "username", "value": "John Doe"}]
70+
)
71+
assert await page.evaluate("() => document.cookie") == "username=John Doe"
72+
assert await page.context.cookies() == [
73+
{
74+
"name": "username",
75+
"value": "John Doe",
76+
"domain": "localhost",
77+
"path": "/",
78+
"expires": -1,
79+
"httpOnly": False,
80+
"secure": False,
81+
"sameSite": "None",
82+
}
83+
]
84+
85+
86+
async def test_context_clear_cookies_should_work(server, launch_persistent):
87+
(page, context) = await launch_persistent()
88+
await page.goto(server.EMPTY_PAGE)
89+
await page.context.addCookies(
90+
[
91+
{"url": server.EMPTY_PAGE, "name": "cookie1", "value": "1"},
92+
{"url": server.EMPTY_PAGE, "name": "cookie2", "value": "2"},
93+
]
94+
)
95+
assert await page.evaluate("document.cookie") == "cookie1=1; cookie2=2"
96+
await page.context.clearCookies()
97+
await page.reload()
98+
assert await page.context.cookies([]) == []
99+
assert await page.evaluate("document.cookie") == ""
100+
101+
102+
async def test_should_not_block_third_party_cookies(
103+
server, launch_persistent, is_chromium, is_firefox
104+
):
105+
(page, context) = await launch_persistent()
106+
await page.goto(server.EMPTY_PAGE)
107+
await page.evaluate(
108+
"""src => {
109+
let fulfill;
110+
const promise = new Promise(x => fulfill = x);
111+
const iframe = document.createElement('iframe');
112+
document.body.appendChild(iframe);
113+
iframe.onload = fulfill;
114+
iframe.src = src;
115+
return promise;
116+
}""",
117+
server.CROSS_PROCESS_PREFIX + "/grid.html",
118+
)
119+
document_cookie = await page.frames[1].evaluate(
120+
"""() => {
121+
document.cookie = 'username=John Doe';
122+
return document.cookie;
123+
}"""
124+
)
125+
126+
await page.waitForTimeout(2000)
127+
allows_third_party = is_chromium or is_firefox
128+
assert document_cookie == ("username=John Doe" if allows_third_party else "")
129+
cookies = await context.cookies(server.CROSS_PROCESS_PREFIX + "/grid.html")
130+
if allows_third_party:
131+
assert cookies == [
132+
{
133+
"domain": "127.0.0.1",
134+
"expires": -1,
135+
"httpOnly": False,
136+
"name": "username",
137+
"path": "/",
138+
"sameSite": "None",
139+
"secure": False,
140+
"value": "John Doe",
141+
}
142+
]
143+
else:
144+
assert cookies == []
145+
146+
147+
async def test_should_support_viewport_option(launch_persistent, utils):
148+
(page, context) = await launch_persistent(viewport={"width": 456, "height": 789})
149+
await utils.verify_viewport(page, 456, 789)
150+
page2 = await context.newPage()
151+
await utils.verify_viewport(page2, 456, 789)
152+
153+
154+
async def test_should_support_device_scale_factor_option(launch_persistent, utils):
155+
(page, context) = await launch_persistent(deviceScaleFactor=3)
156+
assert await page.evaluate("window.devicePixelRatio") == 3
157+
158+
159+
async def test_should_support_user_agent_option(launch_persistent, server):
160+
(page, context) = await launch_persistent(userAgent="foobar")
161+
assert await page.evaluate("() => navigator.userAgent") == "foobar"
162+
[request, _] = await asyncio.gather(
163+
server.wait_for_request("/empty.html"), page.goto(server.EMPTY_PAGE),
164+
)
165+
assert request.getHeader("user-agent") == "foobar"
166+
167+
168+
async def test_should_support_bypass_csp_option(launch_persistent, server):
169+
(page, context) = await launch_persistent(bypassCSP=True)
170+
await page.goto(server.PREFIX + "/csp.html")
171+
await page.addScriptTag(content="window.__injected = 42;")
172+
assert await page.evaluate("() => window.__injected") == 42
173+
174+
175+
async def test_should_support_javascript_enabled_option(launch_persistent, is_webkit):
176+
(page, context) = await launch_persistent(javaScriptEnabled=False)
177+
await page.goto('data:text/html, <script>var something = "forbidden"</script>')
178+
with pytest.raises(Error) as exc:
179+
await page.evaluate("something")
180+
if is_webkit:
181+
assert "Can't find variable: something" in exc.value.message
182+
else:
183+
assert "something is not defined" in exc.value.message
184+
185+
186+
async def test_should_support_http_credentials_option(server, launch_persistent):
187+
(page, context) = await launch_persistent(
188+
httpCredentials={"username": "user", "password": "pass"}
189+
)
190+
server.set_auth("/playground.html", b"user", b"pass")
191+
response = await page.goto(server.PREFIX + "/playground.html")
192+
assert response.status == 200
193+
194+
195+
async def test_should_support_offline_option(server, launch_persistent):
196+
(page, context) = await launch_persistent(offline=True)
197+
with pytest.raises(Error):
198+
await page.goto(server.EMPTY_PAGE)
199+
200+
201+
async def test_should_support_has_touch_option(server, launch_persistent):
202+
(page, context) = await launch_persistent(hasTouch=True)
203+
await page.goto(server.PREFIX + "/mobile.html")
204+
assert await page.evaluate('() => "ontouchstart" in window')
205+
206+
207+
@pytest.mark.skip_browser("firefox")
208+
async def test_should_work_in_persistent_context(server, launch_persistent):
209+
# Firefox does not support mobile.
210+
(page, context) = await launch_persistent(
211+
viewport={"width": 320, "height": 480}, isMobile=True
212+
)
213+
await page.goto(server.PREFIX + "/empty.html")
214+
assert await page.evaluate("() => window.innerWidth") == 980
215+
216+
217+
async def test_should_support_color_scheme_option(server, launch_persistent):
218+
(page, context) = await launch_persistent(colorScheme="dark")
219+
assert (
220+
await page.evaluate('() => matchMedia("(prefers-color-scheme: light)").matches')
221+
is False
222+
)
223+
assert await page.evaluate(
224+
'() => matchMedia("(prefers-color-scheme: dark)").matches'
225+
)
226+
227+
228+
async def test_should_support_timezone_id_option(launch_persistent):
229+
(page, context) = await launch_persistent(timezoneId="America/Jamaica")
230+
assert (
231+
await page.evaluate("() => new Date(1479579154987).toString()")
232+
== "Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)"
233+
)
234+
235+
236+
async def test_should_support_locale_option(launch_persistent):
237+
(page, context) = await launch_persistent(locale="fr-CH")
238+
assert await page.evaluate("() => navigator.language") == "fr-CH"
239+
240+
241+
async def test_should_support_geolocation_and_permission_option(
242+
server, launch_persistent
243+
):
244+
(page, context) = await launch_persistent(
245+
geolocation={"longitude": 10, "latitude": 10}, permissions=["geolocation"]
246+
)
247+
await page.goto(server.EMPTY_PAGE)
248+
geolocation = await page.evaluate(
249+
"""() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => {
250+
resolve({latitude: position.coords.latitude, longitude: position.coords.longitude});
251+
}))"""
252+
)
253+
assert geolocation == {"latitude": 10, "longitude": 10}
254+
255+
256+
async def test_should_support_ignore_https_errors_option(
257+
https_server, launch_persistent
258+
):
259+
(page, context) = await launch_persistent(ignoreHTTPSErrors=True)
260+
response = await page.goto(https_server.EMPTY_PAGE)
261+
assert response.ok
262+
263+
264+
async def test_should_support_extra_http_headers_option(server, launch_persistent):
265+
(page, context) = await launch_persistent(extraHTTPHeaders={"foo": "bar"})
266+
[request, _] = await asyncio.gather(
267+
server.wait_for_request("/empty.html"), page.goto(server.EMPTY_PAGE),
268+
)
269+
assert request.getHeader("foo") == "bar"
270+
271+
272+
async def test_should_accept_user_data_dir(server, tmpdir, launch_persistent):
273+
(page, context) = await launch_persistent()
274+
# Note: we need an open page to make sure its functional.
275+
assert len(os.listdir(tmpdir)) > 0
276+
await context.close()
277+
assert len(os.listdir(tmpdir)) > 0
278+
279+
280+
async def test_should_restore_state_from_userDataDir(
281+
browser_type, launch_arguments, server, tmp_path_factory
282+
):
283+
user_data_dir1 = tmp_path_factory.mktemp("test")
284+
browser_context = await browser_type.launchPersistentContext(
285+
user_data_dir1, **launch_arguments
286+
)
287+
page = await browser_context.newPage()
288+
await page.goto(server.EMPTY_PAGE)
289+
await page.evaluate('() => localStorage.hey = "hello"')
290+
await browser_context.close()
291+
292+
browser_context2 = await browser_type.launchPersistentContext(
293+
user_data_dir1, **launch_arguments
294+
)
295+
page2 = await browser_context2.newPage()
296+
await page2.goto(server.EMPTY_PAGE)
297+
assert await page2.evaluate("() => localStorage.hey") == "hello"
298+
await browser_context2.close()
299+
300+
user_data_dir2 = tmp_path_factory.mktemp("test")
301+
browser_context3 = await browser_type.launchPersistentContext(
302+
user_data_dir2, **launch_arguments
303+
)
304+
page3 = await browser_context3.newPage()
305+
await page3.goto(server.EMPTY_PAGE)
306+
assert await page3.evaluate("() => localStorage.hey") != "hello"
307+
await browser_context3.close()
308+
309+
310+
async def test_should_restore_cookies_from_userDataDir(
311+
browser_type,
312+
launch_arguments,
313+
tmp_path_factory,
314+
server,
315+
is_chromium,
316+
is_win,
317+
is_mac,
318+
):
319+
if is_chromium and (is_win or is_mac):
320+
pytest.skip()
321+
userDataDir = tmp_path_factory.mktemp("1")
322+
browser_context = await browser_type.launchPersistentContext(
323+
userDataDir, **launch_arguments
324+
)
325+
page = await browser_context.newPage()
326+
await page.goto(server.EMPTY_PAGE)
327+
document_cookie = await page.evaluate(
328+
"""() => {
329+
document.cookie = 'doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT';
330+
return document.cookie;
331+
}"""
332+
)
333+
334+
assert document_cookie == "doSomethingOnlyOnce=true"
335+
await browser_context.close()
336+
337+
browser_context2 = await browser_type.launchPersistentContext(
338+
userDataDir, **launch_arguments
339+
)
340+
page2 = await browser_context2.newPage()
341+
await page2.goto(server.EMPTY_PAGE)
342+
assert await page2.evaluate("() => document.cookie") == "doSomethingOnlyOnce=true"
343+
await browser_context2.close()
344+
345+
userDataDir2 = tmp_path_factory.mktemp("2")
346+
browser_context3 = await browser_type.launchPersistentContext(
347+
userDataDir2, **launch_arguments
348+
)
349+
page3 = await browser_context3.newPage()
350+
await page3.goto(server.EMPTY_PAGE)
351+
assert await page3.evaluate("() => document.cookie") != "doSomethingOnlyOnce=true"
352+
await browser_context3.close()
353+
354+
355+
async def test_should_have_default_url_when_launching_browser(launch_persistent):
356+
(page, context) = await launch_persistent()
357+
urls = list(map(lambda p: p.url, context.pages))
358+
assert urls == ["about:blank"]
359+
360+
361+
@pytest.mark.skip_browser("firefox")
362+
async def test_should_throw_if_page_argument_is_passed(
363+
browser_type, server, tmpdir, launch_arguments
364+
):
365+
options = {**launch_arguments, "args": [server.EMPTY_PAGE]}
366+
with pytest.raises(Error) as exc:
367+
await browser_type.launchPersistentContext(tmpdir, **options)
368+
assert "can not specify page" in exc.value.message
369+
370+
371+
async def test_should_fire_close_event_for_a_persistent_context(launch_persistent):
372+
(page, context) = await launch_persistent()
373+
fired_event = asyncio.Future()
374+
context.on("close", lambda: fired_event.set_result(True))
375+
await context.close()
376+
await fired_event

0 commit comments

Comments
 (0)