diff --git a/setup.py b/setup.py index d1ef334..15b0c06 100644 --- a/setup.py +++ b/setup.py @@ -24,10 +24,10 @@ def get_long_description(): packages=["datasette_edit_schema"], entry_points={"datasette": ["edit_schema = datasette_edit_schema"]}, install_requires=[ - "datasette>=0.51", + "datasette>=0.59", "sqlite-utils>=2.21", ], - extras_require={"test": ["pytest", "pytest-asyncio", "httpx"]}, + extras_require={"test": ["pytest", "pytest-asyncio"]}, tests_require=["datasette-edit-schema[test]"], package_data={"datasette_edit_schema": ["templates/*.html", "static/*.js"]}, ) diff --git a/tests/test_edit_schema.py b/tests/test_edit_schema.py index 3315950..7e2a0d3 100644 --- a/tests/test_edit_schema.py +++ b/tests/test_edit_schema.py @@ -2,8 +2,6 @@ from datasette.app import Datasette import sqlite_utils import pytest -import json -import httpx import re whitespace = re.compile(r"\s+") @@ -26,77 +24,64 @@ def db_path(tmpdir): @pytest.mark.asyncio async def test_csrf_required(db_path): ds = Datasette([db_path]) - async with httpx.AsyncClient(app=ds.app()) as client: - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data={"delete_table": "1"}, - allow_redirects=False, - cookies={"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")}, - ) - assert 403 == response.status_code + response = await ds.client.post( + "/edit-schema/data/creatures", + data={"delete_table": "1"}, + cookies={"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")}, + ) + assert response.status_code == 403 @pytest.mark.parametrize("authenticate", [True, False]) @pytest.mark.asyncio async def test_table_actions(db_path, authenticate): ds = Datasette([db_path]) - async with httpx.AsyncClient(app=ds.app()) as client: - cookies = None - if authenticate: - cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} - response = await client.get("http://localhost/data/creatures", cookies=cookies) - assert response.status_code == 200 - fragment = ( - '
  • Edit table schema
  • ' - ) - if authenticate: - # Should have column actions - assert fragment in response.text - else: - assert fragment not in response.text + cookies = None + if authenticate: + cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} + response = await ds.client.get("/data/creatures", cookies=cookies) + assert response.status_code == 200 + fragment = '
  • Edit table schema
  • ' + if authenticate: + # Should have column actions + assert fragment in response.text + else: + assert fragment not in response.text @pytest.mark.asyncio async def test_post_without_operation_raises_error(db_path): ds = Datasette([db_path]) cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} - async with httpx.AsyncClient(app=ds.app()) as client: - # Get a csrftoken - csrftoken = ( - await client.get( - "http://localhost/-/edit-schema/data/creatures", cookies=cookies - ) - ).cookies["ds_csrftoken"] - cookies["ds_csrftoken"] = csrftoken - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data={"csrftoken": csrftoken}, - allow_redirects=False, - cookies=cookies, - ) - assert 400 == response.status_code + # Get a csrftoken + csrftoken = ( + await ds.client.get("/-/edit-schema/data/creatures", cookies=cookies) + ).cookies["ds_csrftoken"] + cookies["ds_csrftoken"] = csrftoken + response = await ds.client.post( + "/-/edit-schema/data/creatures", + data={"csrftoken": csrftoken}, + cookies=cookies, + ) + assert response.status_code == 400 @pytest.mark.asyncio async def test_delete_table(db_path): ds = Datasette([db_path]) - cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} db = sqlite_utils.Database(db_path) assert "creatures" in db.table_names() - async with httpx.AsyncClient(app=ds.app()) as client: - # Get a csrftoken - csrftoken = ( - await client.get( - "http://localhost/-/edit-schema/data/creatures", cookies=cookies - ) - ).cookies["ds_csrftoken"] - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data={"delete_table": "1", "csrftoken": csrftoken}, - allow_redirects=False, - cookies=cookies, - ) - assert 302 == response.status_code + cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} + # Get a csrftoken + csrftoken = ( + await ds.client.get("/-/edit-schema/data/creatures", cookies=cookies) + ).cookies["ds_csrftoken"] + response = await ds.client.post( + "/-/edit-schema/data/creatures", + data={"delete_table": "1", "csrftoken": csrftoken}, + cookies=dict(cookies, ds_csrftoken=csrftoken), + ) + assert response.status_code == 302 assert "creatures" not in db.table_names() @@ -111,25 +96,21 @@ async def test_add_column(db_path, col_type, expected_type): cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} table = db["creatures"] assert {"name": str, "description": str} == table.columns_dict - async with httpx.AsyncClient(app=ds.app()) as client: - # Get a csrftoken - csrftoken = ( - await client.get( - "http://localhost/-/edit-schema/data/creatures", cookies=cookies - ) - ).cookies["ds_csrftoken"] - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data={ - "add_column": "1", - "csrftoken": csrftoken, - "name": "new_col", - "type": col_type, - }, - allow_redirects=False, - cookies=cookies, - ) - assert 302 == response.status_code + # Get a csrftoken + csrftoken = ( + await ds.client.get("/-/edit-schema/data/creatures", cookies=cookies) + ).cookies["ds_csrftoken"] + response = await ds.client.post( + "/-/edit-schema/data/creatures", + data={ + "add_column": "1", + "csrftoken": csrftoken, + "name": "new_col", + "type": col_type, + }, + cookies=dict(cookies, ds_csrftoken=csrftoken), + ) + assert response.status_code == 302 if "ds_messages" in response.cookies: messages = ds.unsign(response.cookies["ds_messages"], "messages") # None of these should be errors @@ -156,24 +137,20 @@ async def test_add_column(db_path, col_type, expected_type): async def test_add_column_errors(db_path, name, type, expected_error): ds = Datasette([db_path]) cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} - async with httpx.AsyncClient(app=ds.app()) as client: - csrftoken = ( - await client.get( - "http://localhost/-/edit-schema/data/creatures", cookies=cookies - ) - ).cookies["ds_csrftoken"] - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data={ - "add_column": "1", - "name": name, - "type": type, - "csrftoken": csrftoken, - }, - allow_redirects=False, - cookies=cookies, - ) - response.status_code == 302 + csrftoken = ( + await ds.client.get("/-/edit-schema/data/creatures", cookies=cookies) + ).cookies["ds_csrftoken"] + response = await ds.client.post( + "/-/edit-schema/data/creatures", + data={ + "add_column": "1", + "name": name, + "type": type, + "csrftoken": csrftoken, + }, + cookies=dict(cookies, ds_csrftoken=csrftoken), + ) + assert response.status_code == 302 assert response.headers["location"] == "/-/edit-schema/data/creatures" messages = ds.unsign(response.cookies["ds_messages"], "messages") assert len(messages) == 1 @@ -227,21 +204,17 @@ async def test_transform_table( db = sqlite_utils.Database(db_path) table = db["creatures"] assert table.columns_dict == {"name": str, "description": str} - async with httpx.AsyncClient(app=ds.app()) as client: - csrftoken = ( - await client.get( - "http://localhost/-/edit-schema/data/creatures", cookies=cookies - ) - ).cookies["ds_csrftoken"] - post_data["csrftoken"] = csrftoken - post_data["action"] = "update_columns" - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data=post_data, - allow_redirects=False, - cookies=cookies, - ) - assert 302 == response.status_code + csrftoken = ( + await ds.client.get("/-/edit-schema/data/creatures", cookies=cookies) + ).cookies["ds_csrftoken"] + post_data["csrftoken"] = csrftoken + post_data["action"] = "update_columns" + response = await ds.client.post( + "/-/edit-schema/data/creatures", + data=post_data, + cookies=dict(cookies, ds_csrftoken=csrftoken), + ) + assert response.status_code == 302 assert table.columns_dict == expected_columns_dict assert [c.name for c in table.columns] == expected_order @@ -249,14 +222,11 @@ async def test_transform_table( @pytest.mark.asyncio async def test_static_assets(db_path): ds = Datasette([db_path]) - async with httpx.AsyncClient(app=ds.app()) as client: - for path in ( - "/-/static-plugins/datasette-edit-schema/draggable.1.0.0-beta.11.bundle.min.js", - ): - response = await client.post( - "http://localhost" + path, - ) - assert response.status_code == 200 + for path in ( + "/-/static-plugins/datasette-edit-schema/draggable.1.0.0-beta.11.bundle.min.js", + ): + response = await ds.client.post(path) + assert response.status_code == 200 @pytest.mark.asyncio @@ -267,19 +237,14 @@ async def test_permission_check(db_path, path): ds = Datasette([db_path]) someuser_cookies = {"ds_actor": ds.sign({"a": {"id": "someuser"}}, "actor")} root_cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} - async with httpx.AsyncClient(app=ds.app()) as client: - response = await client.get( - "http://localhost" + path, - ) - assert response.status_code == 403 - # Should deny with someuser cookie - response = await client.get("http://localhost" + path, cookies=someuser_cookies) - assert response.status_code == 403 - # Should allow with root cookies - response = await client.get( - "http://localhost" + path, cookies=root_cookies, allow_redirects=False - ) - assert response.status_code in (200, 302) + response = await ds.client.get(path) + assert response.status_code == 403 + # Should deny with someuser cookie + response2 = await ds.client.get("" + path, cookies=someuser_cookies) + assert response2.status_code == 403 + # Should allow with root cookies + response3 = await ds.client.get("" + path, cookies=root_cookies) + assert response3.status_code in (200, 302) @pytest.mark.asyncio @@ -296,23 +261,19 @@ async def test_permission_check(db_path, path): async def test_rename_table(db_path, new_name, should_work, expected_message): ds = Datasette([db_path]) cookies = {"ds_actor": ds.sign({"a": {"id": "root"}}, "actor")} - async with httpx.AsyncClient(app=ds.app()) as client: - csrftoken = ( - await client.get( - "http://localhost/-/edit-schema/data/creatures", cookies=cookies - ) - ).cookies["ds_csrftoken"] - response = await client.post( - "http://localhost/-/edit-schema/data/creatures", - data={ - "rename_table": "1", - "name": new_name, - "csrftoken": csrftoken, - }, - allow_redirects=False, - cookies=cookies, - ) - response.status_code == 302 + csrftoken = ( + await ds.client.get("/-/edit-schema/data/creatures", cookies=cookies) + ).cookies["ds_csrftoken"] + response = await ds.client.post( + "/-/edit-schema/data/creatures", + data={ + "rename_table": "1", + "name": new_name, + "csrftoken": csrftoken, + }, + cookies=dict(cookies, ds_csrftoken=csrftoken), + ) + assert response.status_code == 302 if should_work: expected_path = "/-/edit-schema/data/{}".format(new_name) else: