Skip to content

Commit 34c6f1f

Browse files
authored
Merge pull request #182 from autoscrape-labs/fix/issue-181
Add fetch domain commands to `Tab` class
2 parents d462618 + 72f5df6 commit 34c6f1f

File tree

6 files changed

+394
-18
lines changed

6 files changed

+394
-18
lines changed

pydoll/browser/chromium/base.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
DownloadBehavior,
2525
NetworkErrorReason,
2626
PermissionType,
27+
RequestMethod,
2728
ResourceType,
2829
)
2930
from pydoll.exceptions import BrowserNotRunning, FailedToStartBrowser, NoValidTabFound
@@ -425,11 +426,28 @@ async def disable_runtime_events(self):
425426
"""Disable runtime events."""
426427
return await self._connection_handler.execute_command(RuntimeCommands.disable())
427428

428-
async def continue_request(self, request_id: str):
429+
async def continue_request( # noqa: PLR0913, PLR0917
430+
self,
431+
request_id: str,
432+
url: Optional[str] = None,
433+
method: Optional[RequestMethod] = None,
434+
post_data: Optional[str] = None,
435+
headers: Optional[list[HeaderEntry]] = None,
436+
intercept_response: Optional[bool] = None,
437+
):
429438
"""
430439
Continue paused request without modifications.
431440
"""
432-
return await self._execute_command(FetchCommands.continue_request(request_id))
441+
return await self._execute_command(
442+
FetchCommands.continue_request(
443+
request_id=request_id,
444+
url=url,
445+
method=method,
446+
post_data=post_data,
447+
headers=headers,
448+
intercept_response=intercept_response,
449+
)
450+
)
433451

434452
async def fail_request(self, request_id: str, error_reason: NetworkErrorReason):
435453
"""Fail request with error code."""
@@ -439,16 +457,18 @@ async def fulfill_request(
439457
self,
440458
request_id: str,
441459
response_code: int,
442-
response_headers: list[HeaderEntry],
443-
response_body: dict[Any, Any],
460+
response_headers: Optional[list[HeaderEntry]] = None,
461+
body: Optional[str] = None,
462+
response_phrase: Optional[str] = None,
444463
):
445464
"""Fulfill request with response data."""
446465
return await self._execute_command(
447466
FetchCommands.fulfill_request(
448-
request_id,
449-
response_code,
450-
response_headers,
451-
response_body,
467+
request_id=request_id,
468+
response_code=response_code,
469+
response_headers=response_headers,
470+
body=body,
471+
response_phrase=response_phrase,
452472
)
453473
)
454474

pydoll/browser/tab.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@
2626
StorageCommands,
2727
)
2828
from pydoll.connection import ConnectionHandler
29-
from pydoll.constants import By, RequestStage, ResourceType, ScreenshotFormat
29+
from pydoll.constants import (
30+
By,
31+
NetworkErrorReason,
32+
RequestMethod,
33+
RequestStage,
34+
ResourceType,
35+
ScreenshotFormat,
36+
)
3037
from pydoll.elements.mixins import FindElementsMixin
3138
from pydoll.elements.web_element import WebElement
3239
from pydoll.exceptions import (
@@ -42,6 +49,7 @@
4249
)
4350
from pydoll.protocol.base import Response
4451
from pydoll.protocol.dom.types import EventFileChooserOpened
52+
from pydoll.protocol.fetch.types import HeaderEntry
4553
from pydoll.protocol.network.responses import GetResponseBodyResponse
4654
from pydoll.protocol.network.types import Cookie, CookieParam, NetworkLog
4755
from pydoll.protocol.page.events import PageEvent
@@ -668,6 +676,53 @@ async def execute_script(
668676

669677
return await self._execute_script_without_element(script)
670678

679+
# TODO: think about how to remove these duplications with the base class
680+
async def continue_request( # noqa: PLR0913, PLR0917
681+
self,
682+
request_id: str,
683+
url: Optional[str] = None,
684+
method: Optional[RequestMethod] = None,
685+
post_data: Optional[str] = None,
686+
headers: Optional[list[HeaderEntry]] = None,
687+
intercept_response: Optional[bool] = None,
688+
):
689+
"""
690+
Continue paused request without modifications.
691+
"""
692+
return await self._execute_command(
693+
FetchCommands.continue_request(
694+
request_id=request_id,
695+
url=url,
696+
method=method,
697+
post_data=post_data,
698+
headers=headers,
699+
intercept_response=intercept_response,
700+
)
701+
)
702+
703+
async def fail_request(self, request_id: str, error_reason: NetworkErrorReason):
704+
"""Fail request with error code."""
705+
return await self._execute_command(FetchCommands.fail_request(request_id, error_reason))
706+
707+
async def fulfill_request(
708+
self,
709+
request_id: str,
710+
response_code: int,
711+
response_headers: Optional[list[HeaderEntry]] = None,
712+
body: Optional[str] = None,
713+
response_phrase: Optional[str] = None,
714+
):
715+
"""Fulfill request with response data."""
716+
return await self._execute_command(
717+
FetchCommands.fulfill_request(
718+
request_id=request_id,
719+
response_code=response_code,
720+
response_headers=response_headers,
721+
body=body,
722+
response_phrase=response_phrase,
723+
)
724+
)
725+
671726
@asynccontextmanager
672727
async def expect_file_chooser(
673728
self, files: Union[str, Path, list[Union[str, Path]]]

pydoll/commands/fetch_commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def fulfill_request( # noqa: PLR0913, PLR0917
200200
request_id: str,
201201
response_code: int,
202202
response_headers: Optional[list[HeaderEntry]] = None,
203-
body: Optional[dict] = None,
203+
body: Optional[str] = None,
204204
response_phrase: Optional[str] = None,
205205
) -> Command[Response]:
206206
"""

pydoll/protocol/fetch/params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class FulfillRequestParams(CommandParams):
3939
requestId: str
4040
responseCode: int
4141
responseHeaders: NotRequired[list[HeaderEntry]]
42-
body: NotRequired[dict]
42+
body: NotRequired[str]
4343
responsePhrase: NotRequired[str]
4444

4545

tests/test_browser/test_browser_base.py

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import base64
12
from unittest.mock import ANY, AsyncMock, MagicMock, patch
23

34
import pytest
@@ -18,7 +19,7 @@
1819
)
1920
from pydoll.protocol.fetch.events import FetchEvent
2021
from pydoll.connection.connection_handler import ConnectionHandler
21-
from pydoll.constants import DownloadBehavior, PermissionType, NetworkErrorReason
22+
from pydoll.constants import DownloadBehavior, PermissionType, NetworkErrorReason, RequestMethod
2223

2324

2425
class ConcreteBrowser(Browser):
@@ -612,7 +613,57 @@ async def test_disable_runtime_events(mock_browser):
612613
)
613614

614615

615-
# Tests for fail_request and fulfill_request
616+
# Tests for continue_request, fail_request and fulfill_request
617+
@pytest.mark.asyncio
618+
async def test_continue_request(mock_browser):
619+
"""Test continue_request with minimal parameters."""
620+
request_id = 'test_request_123'
621+
622+
await mock_browser.continue_request(request_id)
623+
624+
mock_browser._connection_handler.execute_command.assert_called_with(
625+
FetchCommands.continue_request(
626+
request_id=request_id,
627+
url=None,
628+
method=None,
629+
post_data=None,
630+
headers=None,
631+
intercept_response=None,
632+
), timeout=10
633+
)
634+
635+
636+
@pytest.mark.asyncio
637+
async def test_continue_request_with_all_params(mock_browser):
638+
"""Test continue_request with all parameters."""
639+
request_id = 'test_request_123'
640+
url = 'https://modified-example.com'
641+
method = RequestMethod.POST
642+
post_data = 'modified_data=test'
643+
headers = [{'name': 'Authorization', 'value': 'Bearer token123'}]
644+
intercept_response = True
645+
646+
await mock_browser.continue_request(
647+
request_id=request_id,
648+
url=url,
649+
method=method,
650+
post_data=post_data,
651+
headers=headers,
652+
intercept_response=intercept_response,
653+
)
654+
655+
mock_browser._connection_handler.execute_command.assert_called_with(
656+
FetchCommands.continue_request(
657+
request_id=request_id,
658+
url=url,
659+
method=method,
660+
post_data=post_data,
661+
headers=headers,
662+
intercept_response=intercept_response,
663+
), timeout=10
664+
)
665+
666+
616667
@pytest.mark.asyncio
617668
async def test_fail_request(mock_browser):
618669
"""Test fail_request."""
@@ -628,19 +679,48 @@ async def test_fail_request(mock_browser):
628679

629680
@pytest.mark.asyncio
630681
async def test_fulfill_request(mock_browser):
631-
"""Test fulfill_request."""
682+
"""Test fulfill_request with minimal parameters."""
683+
request_id = 'test_request_123'
684+
response_code = 200
685+
686+
await mock_browser.fulfill_request(request_id, response_code)
687+
688+
mock_browser._connection_handler.execute_command.assert_called_with(
689+
FetchCommands.fulfill_request(
690+
request_id=request_id,
691+
response_code=response_code,
692+
response_headers=None,
693+
body=None,
694+
response_phrase=None,
695+
), timeout=10
696+
)
697+
698+
699+
@pytest.mark.asyncio
700+
async def test_fulfill_request_with_all_params(mock_browser):
701+
"""Test fulfill_request with all parameters."""
632702
request_id = 'test_request_123'
633703
response_code = 200
634704
response_headers = [{'name': 'Content-Type', 'value': 'application/json'}]
635-
response_body = {'status': 'success', 'data': 'test'}
705+
json_response = '{"status": "success", "data": "test"}'
706+
body = base64.b64encode(json_response.encode('utf-8')).decode('utf-8')
707+
response_phrase = 'OK'
636708

637709
await mock_browser.fulfill_request(
638-
request_id, response_code, response_headers, response_body
710+
request_id=request_id,
711+
response_code=response_code,
712+
response_headers=response_headers,
713+
body=body,
714+
response_phrase=response_phrase,
639715
)
640716

641717
mock_browser._connection_handler.execute_command.assert_called_with(
642718
FetchCommands.fulfill_request(
643-
request_id, response_code, response_headers, response_body
719+
request_id=request_id,
720+
response_code=response_code,
721+
response_headers=response_headers,
722+
body=body,
723+
response_phrase=response_phrase,
644724
), timeout=10
645725
)
646726

0 commit comments

Comments
 (0)