Skip to content

Commit decea3c

Browse files
committed
update driver
1 parent 4e90d7b commit decea3c

File tree

8 files changed

+179
-43
lines changed

8 files changed

+179
-43
lines changed

playwright/_impl/_api_structures.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,9 @@ class LocalStorageEntry(TypedDict):
7272
value: str
7373

7474

75-
class OriginState(TypedDict, total=False):
75+
class OriginState(TypedDict):
7676
origin: str
7777
localStorage: List[LocalStorageEntry]
78-
indexedDB: Optional[List[Any]]
7978

8079

8180
class PdfMargins(TypedDict, total=False):

playwright/async_api/_generated.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13469,7 +13469,7 @@ async def storage_state(
1346913469

1347013470
Returns
1347113471
-------
13472-
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}], indexedDB: Union[List[Any], None]}]}
13472+
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}]}]}
1347313473
"""
1347413474

1347513475
return mapping.from_impl(
@@ -13874,7 +13874,7 @@ async def new_context(
1387413874
Dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to fit into
1387513875
800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of each page
1387613876
will be scaled down if necessary to fit the specified size.
13877-
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}], indexedDB: Union[Sequence[Any], None]}]}, None]
13877+
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}]}]}, None]
1387813878
Learn more about [storage state and auth](../auth.md).
1387913879

1388013880
Populates context with given storage state. This option can be used to initialize context with logged-in
@@ -14105,7 +14105,7 @@ async def new_page(
1410514105
Dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to fit into
1410614106
800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of each page
1410714107
will be scaled down if necessary to fit the specified size.
14108-
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}], indexedDB: Union[Sequence[Any], None]}]}, None]
14108+
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}]}]}, None]
1410914109
Learn more about [storage state and auth](../auth.md).
1411014110

1411114111
Populates context with given storage state. This option can be used to initialize context with logged-in
@@ -18672,7 +18672,7 @@ async def storage_state(
1867218672

1867318673
Returns
1867418674
-------
18675-
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}], indexedDB: Union[List[Any], None]}]}
18675+
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}]}]}
1867618676
"""
1867718677

1867818678
return mapping.from_impl(
@@ -18730,7 +18730,7 @@ async def new_context(
1873018730
timeout : Union[float, None]
1873118731
Maximum time in milliseconds to wait for the response. Defaults to `30000` (30 seconds). Pass `0` to disable
1873218732
timeout.
18733-
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}], indexedDB: Union[Sequence[Any], None]}]}, None]
18733+
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}]}]}, None]
1873418734
Populates context with given storage state. This option can be used to initialize context with logged-in
1873518735
information obtained via `browser_context.storage_state()` or `a_pi_request_context.storage_state()`.
1873618736
Either a path to the file with saved storage, or the value returned by one of

playwright/sync_api/_generated.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13506,7 +13506,7 @@ def storage_state(
1350613506

1350713507
Returns
1350813508
-------
13509-
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}], indexedDB: Union[List[Any], None]}]}
13509+
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}]}]}
1351013510
"""
1351113511

1351213512
return mapping.from_impl(
@@ -13911,7 +13911,7 @@ def new_context(
1391113911
Dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to fit into
1391213912
800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of each page
1391313913
will be scaled down if necessary to fit the specified size.
13914-
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}], indexedDB: Union[Sequence[Any], None]}]}, None]
13914+
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}]}]}, None]
1391513915
Learn more about [storage state and auth](../auth.md).
1391613916

1391713917
Populates context with given storage state. This option can be used to initialize context with logged-in
@@ -14144,7 +14144,7 @@ def new_page(
1414414144
Dimensions of the recorded videos. If not specified the size will be equal to `viewport` scaled down to fit into
1414514145
800x800. If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of each page
1414614146
will be scaled down if necessary to fit the specified size.
14147-
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}], indexedDB: Union[Sequence[Any], None]}]}, None]
14147+
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}]}]}, None]
1414814148
Learn more about [storage state and auth](../auth.md).
1414914149

1415014150
Populates context with given storage state. This option can be used to initialize context with logged-in
@@ -18799,7 +18799,7 @@ def storage_state(
1879918799

1880018800
Returns
1880118801
-------
18802-
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}], indexedDB: Union[List[Any], None]}]}
18802+
{cookies: List[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: List[{origin: str, localStorage: List[{name: str, value: str}]}]}
1880318803
"""
1880418804

1880518805
return mapping.from_impl(
@@ -18857,7 +18857,7 @@ def new_context(
1885718857
timeout : Union[float, None]
1885818858
Maximum time in milliseconds to wait for the response. Defaults to `30000` (30 seconds). Pass `0` to disable
1885918859
timeout.
18860-
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}], indexedDB: Union[Sequence[Any], None]}]}, None]
18860+
storage_state : Union[pathlib.Path, str, {cookies: Sequence[{name: str, value: str, domain: str, path: str, expires: float, httpOnly: bool, secure: bool, sameSite: Union["Lax", "None", "Strict"]}], origins: Sequence[{origin: str, localStorage: Sequence[{name: str, value: str}]}]}, None]
1886118861
Populates context with given storage state. This option can be used to initialize context with logged-in
1886218862
information obtained via `browser_context.storage_state()` or `a_pi_request_context.storage_state()`.
1886318863
Either a path to the file with saved storage, or the value returned by one of

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import zipfile
2222
from typing import Dict
2323

24-
driver_version = "1.51.0-beta-1741166263000"
24+
driver_version = "1.51.0-beta-1741261385000"
2525

2626
base_wheel_bundles = [
2727
{

tests/async/test_browsercontext_storage_state.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import json
1717
from pathlib import Path
1818

19-
from playwright.async_api import Browser, BrowserContext, Page
19+
from playwright.async_api import Browser, BrowserContext, Page, StorageState
2020
from tests.server import Server
2121

2222

@@ -44,30 +44,30 @@ async def test_should_capture_local_storage(context: BrowserContext) -> None:
4444

4545

4646
async def test_should_set_local_storage(browser: Browser) -> None:
47-
context = await browser.new_context(
48-
storage_state={
49-
"origins": [
47+
storage_state: StorageState = {
48+
"origins": [
49+
{
50+
"origin": "https://www.example.com",
51+
"localStorage": [{"name": "name1", "value": "value1"}],
52+
}
53+
]
54+
}
55+
# We intentionally hide the indexed_db part in our API for now
56+
storage_state["origins"][0]["indexedDB"] = [ # type: ignore
57+
{
58+
"name": "db",
59+
"version": 42,
60+
"stores": [
5061
{
51-
"origin": "https://www.example.com",
52-
"localStorage": [{"name": "name1", "value": "value1"}],
53-
"indexedDB": [
54-
{
55-
"name": "db",
56-
"version": 42,
57-
"stores": [
58-
{
59-
"name": "store",
60-
"autoIncrement": False,
61-
"records": [{"key": "bar", "value": "foo"}],
62-
"indexes": [],
63-
}
64-
],
65-
}
66-
],
62+
"name": "store",
63+
"autoIncrement": False,
64+
"records": [{"key": "bar", "value": "foo"}],
65+
"indexes": [],
6766
}
68-
]
67+
],
6968
}
70-
)
69+
]
70+
context = await browser.new_context(storage_state=storage_state)
7171

7272
page = await context.new_page()
7373
await page.route(

tests/sync/test_browsercontext_storage_state.py

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
import json
1616
from pathlib import Path
1717

18-
from playwright.sync_api import Browser, BrowserContext
18+
from playwright.sync_api import Browser, BrowserContext, Page, StorageState
19+
from tests.server import Server
1920

2021

2122
def test_should_capture_local_storage(context: BrowserContext) -> None:
@@ -41,22 +42,53 @@ def test_should_capture_local_storage(context: BrowserContext) -> None:
4142

4243

4344
def test_should_set_local_storage(browser: Browser) -> None:
44-
context = browser.new_context(
45-
storage_state={
46-
"origins": [
45+
storage_state: StorageState = {
46+
"origins": [
47+
{
48+
"origin": "https://www.example.com",
49+
"localStorage": [{"name": "name1", "value": "value1"}],
50+
}
51+
]
52+
}
53+
# We intentionally hide the indexed_db part in our API for now
54+
storage_state["origins"][0]["indexedDB"] = [ # type: ignore
55+
{
56+
"name": "db",
57+
"version": 42,
58+
"stores": [
4759
{
48-
"origin": "https://www.example.com",
49-
"localStorage": [{"name": "name1", "value": "value1"}],
60+
"name": "store",
61+
"autoIncrement": False,
62+
"records": [{"key": "bar", "value": "foo"}],
63+
"indexes": [],
5064
}
51-
]
65+
],
5266
}
53-
)
67+
]
68+
context = browser.new_context(storage_state=storage_state)
5469

5570
page = context.new_page()
5671
page.route("**/*", lambda route: route.fulfill(body="<html></html>"))
5772
page.goto("https://www.example.com")
5873
local_storage = page.evaluate("window.localStorage")
5974
assert local_storage == {"name1": "value1"}
75+
76+
indexed_db = page.evaluate(
77+
"""async () => {
78+
return new Promise((resolve, reject) => {
79+
const openRequest = indexedDB.open('db', 42);
80+
openRequest.addEventListener('success', () => {
81+
const db = openRequest.result;
82+
const transaction = db.transaction('store', 'readonly');
83+
const getRequest = transaction.objectStore('store').get('bar');
84+
getRequest.addEventListener('success', () => resolve(getRequest.result));
85+
getRequest.addEventListener('error', () => reject(getRequest.error));
86+
});
87+
openRequest.addEventListener('error', () => reject(openRequest.error));
88+
});
89+
}"""
90+
)
91+
assert indexed_db == "foo"
6092
context.close()
6193

6294

@@ -95,3 +127,48 @@ def test_should_round_trip_through_the_file(
95127
cookie = page2.evaluate("document.cookie")
96128
assert cookie == "username=John Doe"
97129
context2.close()
130+
131+
132+
def test_should_serialise_indexed_db(page: Page, server: Server) -> None:
133+
page.goto(server.EMPTY_PAGE)
134+
page.evaluate(
135+
"""async () => {
136+
await new Promise((resolve, reject) => {
137+
const openRequest = indexedDB.open('db', 42);
138+
openRequest.onupgradeneeded = () => {
139+
openRequest.result.createObjectStore('store');
140+
};
141+
openRequest.onsuccess = () => {
142+
const request = openRequest.result.transaction('store', 'readwrite')
143+
.objectStore('store')
144+
.put('foo', 'bar');
145+
request.addEventListener('success', resolve);
146+
request.addEventListener('error', reject);
147+
};
148+
});
149+
}"""
150+
)
151+
assert page.context.storage_state() == {"cookies": [], "origins": []}
152+
assert page.context.storage_state(indexed_db=True) == {
153+
"cookies": [],
154+
"origins": [
155+
{
156+
"origin": f"http://localhost:{server.PORT}",
157+
"localStorage": [],
158+
"indexedDB": [
159+
{
160+
"name": "db",
161+
"version": 42,
162+
"stores": [
163+
{
164+
"name": "store",
165+
"autoIncrement": False,
166+
"records": [{"key": "bar", "value": "foo"}],
167+
"indexes": [],
168+
}
169+
],
170+
}
171+
],
172+
}
173+
],
174+
}

tests/sync/test_fetch_global.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,41 @@ def test_should_serialize_null_values_in_json(
323323
assert response.status == 200
324324
assert response.text() == '{"foo": null}'
325325
request.dispose()
326+
327+
328+
def test_should_throw_when_fail_on_status_code_is_true(
329+
playwright: Playwright, server: Server
330+
) -> None:
331+
server.set_route(
332+
"/empty.html",
333+
lambda req: (
334+
req.setResponseCode(404),
335+
req.setHeader("Content-Length", "10"),
336+
req.setHeader("Content-Type", "text/plain"),
337+
req.write(b"Not found."),
338+
req.finish(),
339+
),
340+
)
341+
request = playwright.request.new_context(fail_on_status_code=True)
342+
with pytest.raises(Error, match="404 Not Found"):
343+
request.fetch(server.EMPTY_PAGE)
344+
request.dispose()
345+
346+
347+
def test_should_not_throw_when_fail_on_status_code_is_false(
348+
playwright: Playwright, server: Server
349+
) -> None:
350+
server.set_route(
351+
"/empty.html",
352+
lambda req: (
353+
req.setResponseCode(404),
354+
req.setHeader("Content-Length", "10"),
355+
req.setHeader("Content-Type", "text/plain"),
356+
req.write(b"Not found."),
357+
req.finish(),
358+
),
359+
)
360+
request = playwright.request.new_context(fail_on_status_code=False)
361+
response = request.fetch(server.EMPTY_PAGE)
362+
assert response.status == 404
363+
request.dispose()

tests/sync/test_locators.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,28 @@ def test_should_combine_visible_with_other_selectors(page: Page) -> None:
493493
)
494494

495495

496+
def test_should_support_filter_visible(page: Page) -> None:
497+
page.set_content(
498+
"""<div>
499+
<div class="item" style="display: none">Hidden data0</div>
500+
<div class="item">visible data1</div>
501+
<div class="item" style="display: none">Hidden data1</div>
502+
<div class="item">visible data2</div>
503+
<div class="item" style="display: none">Hidden data2</div>
504+
<div class="item">visible data3</div>
505+
</div>
506+
"""
507+
)
508+
locator = page.locator(".item").filter(visible=True).nth(1)
509+
expect(locator).to_have_text("visible data2")
510+
expect(
511+
page.locator(".item").filter(visible=True).get_by_text("data3")
512+
).to_have_text("visible data3")
513+
expect(
514+
page.locator(".item").filter(visible=False).get_by_text("data1")
515+
).to_have_text("Hidden data1")
516+
517+
496518
def test_locator_count_should_work_with_deleted_map_in_main_world(page: Page) -> None:
497519
page.evaluate("Map = 1")
498520
page.locator("#searchResultTableDiv .x-grid3-row").count()

0 commit comments

Comments
 (0)