import pytest
from eggfetch.compat.httpx import (
Client,
MockTransport,
QueryParams,
Request,
Response,
URL,
)
from eggfetch.compat.httpx._cookies import Cookies
from eggfetch.compat.httpx._headers import Headers
class TestDuplicateCookiePreservation:
def test_set_overwrites_same_name(self):
cookies = Cookies()
cookies.set("session", "val1", domain=".example.com", path="/")
cookies.set("session", "val2", domain=".example.com", path="/")
items = list(cookies.items())
assert len(items) == 1
assert cookies.get("session") == "val2"
def test_set_different_domain_preserves(self):
cookies = Cookies()
cookies.set("session", "val1", domain=".example.com")
cookies.set("session", "val2", domain=".api.example.com")
items = list(cookies.items())
assert len(items) == 2
def test_different_names_preserved(self):
cookies = Cookies()
cookies.set("session", "val1")
cookies.set("token", "val2")
items = list(cookies.items())
assert len(items) == 2
def test_duplicate_cookie_header_wired(self):
def handler(request):
return Response(
200,
headers=[
("set-cookie", "a=1; path=/"),
("set-cookie", "b=2; path=/api"),
("set-cookie", "c=3; path=/other"),
],
)
with Client(transport=MockTransport(handler)) as client:
resp = client.get("http://testserver/")
set_cookie_headers = resp.headers.multi_items()
set_cookies = [v for k, v in set_cookie_headers if k.lower() == "set-cookie"]
assert len(set_cookies) == 3
class TestURLPercentEncoding:
def test_percent_encoded_path_preserved(self):
url = URL("http://example.com/path%20with%20spaces")
assert "%20" in str(url) or "path%20with%20spaces" in str(url)
def test_userinfo_preserved(self):
url = URL("http://user:pass@example.com/")
assert url.username == "user"
assert url.password == "pass"
def test_query_params_ordering_and_duplicates(self):
qp = QueryParams("a=1&a=2&b=&a=3")
items = qp.multi_items()
assert items == [("a", "1"), ("a", "2"), ("b", ""), ("a", "3")]
def test_query_params_merge_preserves_order(self):
base = QueryParams("x=1&y=2")
extra = QueryParams("x=3&z=4")
base.merge(extra) items = base.multi_items()
assert items == [("x", "1"), ("y", "2"), ("x", "3"), ("z", "4")]
class TestResponseHistoryAttachment:
def test_redirect_history_has_requests(self):
def handler(request):
if request.url.path == "/start":
return Response(302, headers=[("location", "http://testserver/end")])
return Response(200, text="done")
with Client(transport=MockTransport(handler), follow_redirects=False) as client:
resp = client.get("http://testserver/start")
assert resp.status_code == 302
assert resp.request is not None
assert resp.request.url.path == "/start"
class TestDuplicateHeadersPreserved:
def test_duplicate_set_cookie_independent(self):
def handler(request):
return Response(
200,
headers=[
("set-cookie", "a=1"),
("set-cookie", "b=2"),
("set-cookie", "a=3"),
],
)
with Client(transport=MockTransport(handler)) as client:
resp = client.get("http://testserver/")
set_cookies = [v for k, v in resp.headers.multi_items() if k.lower() == "set-cookie"]
assert len(set_cookies) == 3
assert "a=1" in set_cookies
assert "b=2" in set_cookies
assert "a=3" in set_cookies
def test_raw_header_ordering_preserved(self):
def handler(request):
return Response(
200,
headers=[
("x-first", "1"),
("x-second", "2"),
("x-first", "3"),
],
)
with Client(transport=MockTransport(handler)) as client:
resp = client.get("http://testserver/")
items = resp.headers.multi_items()
first_headers = [(k, v) for k, v in items if k == "x-first"]
assert first_headers == [("x-first", "1"), ("x-first", "3")]