diff --git a/setup.py b/setup.py index 78557ea..048546d 100644 --- a/setup.py +++ b/setup.py @@ -39,7 +39,7 @@ setup( "pytest-httpx", "cogapp", "pytest-mock", - "datasette", + "datasette>=1.0a2", ] }, python_requires=">=3.7", diff --git a/tests/test_insert.py b/tests/test_insert.py index 8e9b794..378150d 100644 --- a/tests/test_insert.py +++ b/tests/test_insert.py @@ -1,7 +1,18 @@ +import asyncio from click.testing import CliRunner +from datasette.app import Datasette from dclient.cli import cli +import httpx import json import pathlib +import pytest + + +@pytest.fixture +def non_mocked_hosts(): + # This ensures httpx-mock will not affect Datasette's own + # httpx calls made in the tests by datasette.client: + return ["localhost"] def test_insert_mocked(httpx_mock, tmpdir): @@ -10,13 +21,12 @@ def test_insert_mocked(httpx_mock, tmpdir): "ok": True, "database": "data", "table": "table1", - "table_url": "http://localhost:8012/data/table1", - "table_api_url": "http://localhost:8012/data/table1.json", + "table_url": "http://datasette.example.com/data/table1", + "table_api_url": "http://datasette.example.com/data/table1.json", "schema": "CREATE TABLE [table1] (...)", "row_count": 100, } ) - (tmpdir / "data.csv") path = pathlib.Path(tmpdir) / "data.csv" path.write_text("a,b,c\n1,2,3\n") runner = CliRunner() @@ -24,7 +34,7 @@ def test_insert_mocked(httpx_mock, tmpdir): cli, [ "insert", - "https://localhost:8012/data", + "https://datasette.example.com/data", "table1", str(path), "--csv", @@ -38,3 +48,68 @@ def test_insert_mocked(httpx_mock, tmpdir): request = httpx_mock.get_request() assert request.headers["authorization"] == "Bearer x" assert json.loads(request.read()) == {"rows": [{"a": 1, "b": 2, "c": 3}]} + + +def test_insert_against_datasette(httpx_mock, tmpdir): + ds = Datasette( + metadata={ + "permissions": { + "create-table": {"id": "*"}, + "insert-row": {"id": "*"}, + "update-row": {"id": "*"}, + } + } + ) + ds.add_memory_database("data") + + token = ds.create_token("actor") + + loop = asyncio.get_event_loop() + + def custom_response(request: httpx.Request): + # Need to run this in async loop, because dclient itself uses + # sync HTTPX and not async HTTPX + async def run(): + response = await ds.client.request( + request.method, + request.url.path, + json=json.loads(request.read()), + headers=request.headers, + ) + # Create a fresh response to avoid an error where stream has been consumed + return httpx.Response( + status_code=response.status_code, + headers=response.headers, + content=response.content, + ) + + return loop.run_until_complete(run()) + + httpx_mock.add_callback(custom_response) + + path = pathlib.Path(tmpdir) / "data.csv" + path.write_text("a,b,c\n1,2,3\n") + runner = CliRunner() + result = runner.invoke( + cli, + [ + "insert", + "http://datasette.example.com/data", + "table1", + str(path), + "--csv", + "--token", + token, + "--create", + ], + catch_exceptions=False, + ) + assert result.exit_code == 0 + + # Datasette should have the new rows + async def fetch_table(): + response = await ds.client.get("/data/table1.json?_shape=array") + return response + + response = loop.run_until_complete(fetch_table()) + assert response.json() == [{"rowid": 1, "a": 1, "b": 2, "c": 3}]