prkumar / uplink

A Declarative HTTP Client for Python
https://uplink.readthedocs.io/
MIT License
1.07k stars 61 forks source link

Query params are being encoded too early so cannot be effectively mocked #288

Open ghandic opened 1 year ago

ghandic commented 1 year ago

Describe the bug Query params are being encoded too early so cannot be effectively mocked

To Reproduce See full dialog in https://github.com/chassing/uplink-httpx/issues/6

Expected behavior See full dialog in https://github.com/chassing/uplink-httpx/issues/6

Additional context This seems to be an edge case when the characters are need percent url encoding

ghandic commented 1 year ago

I found that if I set encoded=True then it is passing, though this seems a little sketchy :D as httpx seems to auto encode but other http clients might not

import httpx
import respx
from fastapi import FastAPI, Query
from uplink import Consumer
from uplink import Query as Q
from uplink import get, returns
from uplink_httpx import HttpxClient

### Given: Mock Server
BASE_URL = "https://mock.api/"

app = FastAPI()

@app.get("/user")
def get_user(select: str = Query(alias="$select")):
    return {"id": select}

mock_api = respx.mock(base_url=BASE_URL, assert_all_called=False)
mock_api.route().mock(side_effect=respx.ASGIHandler(app))

### When: Client
class BasicClient(Consumer):
    @get("user")
    @returns.json()
    def user(self, select: Q("$select", encoded=True)):
        ...

### Then: Should work with either raw client or uplink client
@mock_api
async def test_raw():
    client = BasicClient(base_url=BASE_URL, client=HttpxClient())
    resp = await client.user(select=123)
    assert resp.status_code == 200
    assert resp.json() == {"id": "123"}

@mock_api
async def test_uplink():
    resp = await httpx.AsyncClient().get(f"{BASE_URL}user?$select=123")
    assert resp.status_code == 200
    assert resp.json() == {"id": "123"}

All passing with the above