3636 SetCookieParam ,
3737 StorageState ,
3838)
39- from playwright ._impl ._api_types import Error
4039from playwright ._impl ._artifact import Artifact
4140from playwright ._impl ._cdp_session import CDPSession
4241from playwright ._impl ._connection import (
4342 ChannelOwner ,
43+ filter_none ,
4444 from_channel ,
4545 from_nullable_channel ,
4646)
4747from playwright ._impl ._console_message import ConsoleMessage
4848from playwright ._impl ._dialog import Dialog
49+ from playwright ._impl ._errors import Error , TargetClosedError
4950from playwright ._impl ._event_context_manager import EventContextManagerImpl
5051from playwright ._impl ._fetch import APIRequestContext
5152from playwright ._impl ._frame import Frame
7071from playwright ._impl ._network import Request , Response , Route , serialize_headers
7172from playwright ._impl ._page import BindingCall , Page , Worker
7273from playwright ._impl ._tracing import Tracing
73- from playwright ._impl ._wait_helper import WaitHelper
74+ from playwright ._impl ._waiter import Waiter
7475from playwright ._impl ._web_error import WebError
7576
7677if TYPE_CHECKING : # pragma: no cover
@@ -194,6 +195,7 @@ def __init__(
194195 self .once (
195196 self .Events .Close , lambda context : self ._closed_future .set_result (True )
196197 )
198+ self ._close_reason : Optional [str ] = None
197199 self ._set_event_to_subscription_mapping (
198200 {
199201 BrowserContext .Events .Console : "console" ,
@@ -433,26 +435,27 @@ def expect_event(
433435 ) -> EventContextManagerImpl :
434436 if timeout is None :
435437 timeout = self ._timeout_settings .timeout ()
436- wait_helper = WaitHelper (self , f"browser_context.expect_event({ event } )" )
437- wait_helper .reject_on_timeout (
438+ waiter = Waiter (self , f"browser_context.expect_event({ event } )" )
439+ waiter .reject_on_timeout (
438440 timeout , f'Timeout { timeout } ms exceeded while waiting for event "{ event } "'
439441 )
440442 if event != BrowserContext .Events .Close :
441- wait_helper .reject_on_event (
442- self , BrowserContext .Events .Close , Error ( "Context closed" )
443+ waiter .reject_on_event (
444+ self , BrowserContext .Events .Close , lambda : TargetClosedError ( )
443445 )
444- wait_helper .wait_for_event (self , event , predicate )
445- return EventContextManagerImpl (wait_helper .result ())
446+ waiter .wait_for_event (self , event , predicate )
447+ return EventContextManagerImpl (waiter .result ())
446448
447449 def _on_close (self ) -> None :
448450 if self ._browser :
449451 self ._browser ._contexts .remove (self )
450452
451453 self .emit (BrowserContext .Events .Close , self )
452454
453- async def close (self ) -> None :
455+ async def close (self , reason : str = None ) -> None :
454456 if self ._close_was_called :
455457 return
458+ self ._close_reason = reason
456459 self ._close_was_called = True
457460
458461 async def _inner_close () -> None :
@@ -479,7 +482,7 @@ async def _inner_close() -> None:
479482 await har .delete ()
480483
481484 await self ._channel ._connection .wrap_api_call (_inner_close , True )
482- await self ._channel .send ("close" )
485+ await self ._channel .send ("close" , filter_none ({ "reason" : reason }) )
483486 await self ._closed_future
484487
485488 async def storage_state (self , path : Union [str , Path ] = None ) -> StorageState :
@@ -488,6 +491,13 @@ async def storage_state(self, path: Union[str, Path] = None) -> StorageState:
488491 await async_writefile (path , json .dumps (result ))
489492 return result
490493
494+ def _effective_close_reason (self ) -> Optional [str ]:
495+ if self ._close_reason :
496+ return self ._close_reason
497+ if self ._browser :
498+ return self ._browser ._close_reason
499+ return None
500+
491501 async def wait_for_event (
492502 self , event : str , predicate : Callable = None , timeout : float = None
493503 ) -> Any :
0 commit comments