insert test that exercises against an in-memory Datasette instance, refs #8

This commit is contained in:
Simon Willison 2023-07-24 15:18:54 -07:00
commit c03cbb2bbc
2 changed files with 80 additions and 5 deletions

View file

@ -39,7 +39,7 @@ setup(
"pytest-httpx", "pytest-httpx",
"cogapp", "cogapp",
"pytest-mock", "pytest-mock",
"datasette", "datasette>=1.0a2",
] ]
}, },
python_requires=">=3.7", python_requires=">=3.7",

View file

@ -1,7 +1,18 @@
import asyncio
from click.testing import CliRunner from click.testing import CliRunner
from datasette.app import Datasette
from dclient.cli import cli from dclient.cli import cli
import httpx
import json import json
import pathlib 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): def test_insert_mocked(httpx_mock, tmpdir):
@ -10,13 +21,12 @@ def test_insert_mocked(httpx_mock, tmpdir):
"ok": True, "ok": True,
"database": "data", "database": "data",
"table": "table1", "table": "table1",
"table_url": "http://localhost:8012/data/table1", "table_url": "http://datasette.example.com/data/table1",
"table_api_url": "http://localhost:8012/data/table1.json", "table_api_url": "http://datasette.example.com/data/table1.json",
"schema": "CREATE TABLE [table1] (...)", "schema": "CREATE TABLE [table1] (...)",
"row_count": 100, "row_count": 100,
} }
) )
(tmpdir / "data.csv")
path = pathlib.Path(tmpdir) / "data.csv" path = pathlib.Path(tmpdir) / "data.csv"
path.write_text("a,b,c\n1,2,3\n") path.write_text("a,b,c\n1,2,3\n")
runner = CliRunner() runner = CliRunner()
@ -24,7 +34,7 @@ def test_insert_mocked(httpx_mock, tmpdir):
cli, cli,
[ [
"insert", "insert",
"https://localhost:8012/data", "https://datasette.example.com/data",
"table1", "table1",
str(path), str(path),
"--csv", "--csv",
@ -38,3 +48,68 @@ def test_insert_mocked(httpx_mock, tmpdir):
request = httpx_mock.get_request() request = httpx_mock.get_request()
assert request.headers["authorization"] == "Bearer x" assert request.headers["authorization"] == "Bearer x"
assert json.loads(request.read()) == {"rows": [{"a": 1, "b": 2, "c": 3}]} 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}]