Skip to content

fix: fulfill with json #1700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions playwright/_impl/_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import base64
import inspect
import json
import json as json_utils
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This definitely works, but perhaps there is a more idiomatic and future proof approach. The original issue was missed since the parameter is/was typed as Any so json.dumps was valid from the typechecker's perspective, but in reality was wrong since json shadowed and referred to the method's parameter.

import mimetypes
import sys
from collections import defaultdict
Expand Down Expand Up @@ -288,6 +289,12 @@ async def fulfill(
) -> None:
self._check_not_handled()
params = locals_to_params(locals())

if json is not None:
if body is not None:
raise Error("Can specify either body or json parameters")
body = json_utils.dumps(json)

if response:
del params["response"]
params["status"] = (
Expand All @@ -298,8 +305,6 @@ async def fulfill(
)
from playwright._impl._fetch import APIResponse

if json is not None:
body = json.dumps(json)
if body is None and path is None and isinstance(response, APIResponse):
if response._request._connection is self._connection:
params["fetchResponseUid"] = response._fetch_uid
Expand Down
51 changes: 51 additions & 0 deletions tests/async/test_request_fulfill.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import json

from playwright.async_api import Page, Route
from tests.server import Server

Expand All @@ -25,3 +27,52 @@ async def handle(route: Route):
response = await page.goto(server.PREFIX + "/title.html")
assert response.status == 200
assert await page.title() == "Woof-Woof"


async def test_should_fulfill_json(page: Page, server: Server) -> None:
async def handle(route: Route) -> None:
await route.fulfill(status=201, headers={"foo": "bar"}, json={"bar": "baz"})

await page.route("**/*", handle)

response = await page.goto(server.EMPTY_PAGE)
assert response
assert response.status == 201
assert response.headers["content-type"] == "application/json"
assert json.loads(await page.evaluate("document.body.textContent")) == {
"bar": "baz"
}


async def test_should_fulfill_json_overriding_existing_response(
page: Page, server: Server
) -> None:
server.set_route(
"/tags",
lambda request: (
request.setHeader("foo", "bar"),
request.write('{"tags": ["a", "b"]}'.encode()),
request.finish(),
),
)

original = {}

async def handle(route: Route) -> None:
response = await route.fetch()
json = await response.json()
original["tags"] = json["tags"]
json["tags"] = ["c"]
await route.fulfill(response=response, json=json)

await page.route("**/*", handle)

response = await page.goto(server.PREFIX + "/tags")
assert response
assert response.status == 200
assert response.headers["content-type"] == "application/json"
assert response.headers["foo"] == "bar"
assert original["tags"] == ["a", "b"]
assert json.loads(await page.evaluate("document.body.textContent")) == {
"tags": ["c"]
}
47 changes: 47 additions & 0 deletions tests/sync/test_request_fulfill.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import json

from playwright.sync_api import Page, Route
from tests.server import Server

Expand All @@ -26,3 +28,48 @@ def handle(route: Route) -> None:
assert response
assert response.status == 200
assert page.title() == "Woof-Woof"


def test_should_fulfill_json(page: Page, server: Server) -> None:
def handle(route: Route) -> None:
route.fulfill(status=201, headers={"foo": "bar"}, json={"bar": "baz"})

page.route("**/*", handle)

response = page.goto(server.EMPTY_PAGE)
assert response
assert response.status == 201
assert response.headers["content-type"] == "application/json"
assert json.loads(page.evaluate("document.body.textContent")) == {"bar": "baz"}


def test_should_fulfill_json_overriding_existing_response(
page: Page, server: Server
) -> None:
server.set_route(
"/tags",
lambda request: (
request.setHeader("foo", "bar"),
request.write('{"tags": ["a", "b"]}'.encode()),
request.finish(),
),
)

original = {}

def handle(route: Route) -> None:
response = route.fetch()
json = response.json()
original["tags"] = json["tags"]
json["tags"] = ["c"]
route.fulfill(response=response, json=json)

page.route("**/*", handle)

response = page.goto(server.PREFIX + "/tags")
assert response
assert response.status == 200
assert response.headers["content-type"] == "application/json"
assert response.headers["foo"] == "bar"
assert original["tags"] == ["a", "b"]
assert json.loads(page.evaluate("document.body.textContent")) == {"tags": ["c"]}