Skip to content

Commit 87dceff

Browse files
authored
feat(gather): introduce sync gather for easier async tests migration (#131)
1 parent fdf2759 commit 87dceff

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

playwright/sync_base.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@
1313
# limitations under the License.
1414

1515
import asyncio
16-
from typing import Any, Callable, Coroutine, Generic, Optional, TypeVar, cast
16+
from typing import (
17+
Any,
18+
Callable,
19+
Coroutine,
20+
Dict,
21+
Generic,
22+
List,
23+
Optional,
24+
TypeVar,
25+
cast,
26+
)
1727

1828
import greenlet
1929

@@ -109,3 +119,35 @@ def once(self, event_name: str, handler: Any) -> None:
109119

110120
def remove_listener(self, event_name: str, handler: Any) -> None:
111121
self._impl_obj.remove_listener(event_name, handler)
122+
123+
def _gather(self, *actions: Callable) -> List[Any]:
124+
g_self = greenlet.getcurrent()
125+
results: Dict[Callable, Any] = {}
126+
exceptions: List[Exception] = []
127+
128+
def action_wrapper(action: Callable) -> Callable:
129+
def body() -> Any:
130+
try:
131+
results[action] = action()
132+
except Exception as e:
133+
results[action] = e
134+
exceptions.append(e)
135+
g_self.switch()
136+
137+
return body
138+
139+
async def task() -> None:
140+
for action in actions:
141+
g = greenlet.greenlet(action_wrapper(action))
142+
g.switch()
143+
144+
self._loop.create_task(task())
145+
146+
while len(results) < len(actions):
147+
dispatcher_fiber_.switch()
148+
149+
asyncio._set_running_loop(self._loop)
150+
if exceptions:
151+
raise exceptions[0]
152+
153+
return list(map(lambda action: results[action], actions))

tests/async/test_navigation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ async def test_expect_navigation_should_work_for_cross_process_navigations(
658658
await goto_task
659659

660660

661-
@pytest.mark.skip_browser("webkit")
661+
@pytest.mark.skip("flaky, investigate")
662662
async def test_wait_for_load_state_should_pick_up_ongoing_navigation(page, server):
663663
requests = []
664664

tests/sync/test_sync.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,13 @@ def test_sync_set_default_timeout(page):
187187
with pytest.raises(TimeoutError) as exc:
188188
page.waitForFunction("false")
189189
assert "Timeout 1ms exceeded." in exc.value.message
190+
191+
192+
def test_close_should_reject_all_promises(context):
193+
new_page = context.newPage()
194+
with pytest.raises(Error) as exc_info:
195+
new_page._gather(
196+
lambda: new_page.evaluate("() => new Promise(r => {})"),
197+
lambda: new_page.close(),
198+
)
199+
assert "Protocol error" in exc_info.value.message

0 commit comments

Comments
 (0)