dclient auth commands

Closes #3
This commit is contained in:
Simon Willison 2023-07-17 16:23:53 -07:00 • committed by GitHub
commit 8a205d81a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 304 additions and 12 deletions

41
tests/test_cli_auth.py Normal file
View file

@ -0,0 +1,41 @@
from click.testing import CliRunner
from dclient.cli import cli
import pathlib
import json
def test_auth(mocker, tmpdir):
mocker.patch("dclient.cli.get_config_dir", return_value=pathlib.Path(tmpdir))
runner = CliRunner()
result = runner.invoke(cli, ["auth", "list"])
assert result.exit_code == 0
assert result.output.startswith("Tokens file:")
# Should only have one line
assert len([line for line in result.output.split("\n") if line.strip()]) == 1
# Now add a token
result2 = runner.invoke(cli, ["auth", "add", "https://example.com"], input="xyz\n")
assert result2.exit_code == 0
# Check the tokens file
auth_file = pathlib.Path(tmpdir) / "auth.json"
assert json.loads(auth_file.read_text()) == {"https://example.com": "xyz"}
# auth list should show that now
result3 = runner.invoke(cli, ["auth", "list"])
assert result3.output.startswith("Tokens file:")
assert "https://example.com" in result3.output
# Remove should fail with an incorrect URL
result4 = runner.invoke(cli, ["auth", "remove", "https://example.com/foo"])
assert result4.exit_code == 1
assert result4.output == "Error: No such URL or alias\n"
# Remove should work with the correct URL
result5 = runner.invoke(cli, ["auth", "remove", "https://example.com"])
assert result5.exit_code == 0
assert result5.output == ""
# Check the tokens file
auth_file = pathlib.Path(tmpdir) / "auth.json"
assert json.loads(auth_file.read_text()) == {}

View file

@ -2,6 +2,7 @@ from click.testing import CliRunner
from dclient.cli import cli
import json
import pathlib
import pytest
def test_query_error(httpx_mock):
@ -17,10 +18,14 @@ def test_query_error(httpx_mock):
runner = CliRunner()
result = runner.invoke(cli, ["query", "https://example.com", "hello"])
assert result.exit_code == 1
assert result.output == "Error: Invalid SQL: Statement must be a SELECT\n"
assert (
result.output
== "Error: 400 status code. Invalid SQL: Statement must be a SELECT\n"
)
def test_query(httpx_mock):
@pytest.mark.parametrize("with_token", (False, True))
def test_query(httpx_mock, with_token):
httpx_mock.add_response(
json={
"ok": True,
@ -37,10 +42,22 @@ def test_query(httpx_mock):
status_code=200,
)
runner = CliRunner()
result = runner.invoke(cli, ["query", "https://example.com", "hello"])
args = ["query", "https://example.com", "hello"]
if with_token:
args.append("--token")
args.append("xyz")
result = runner.invoke(cli, args)
assert result.exit_code == 0
assert json.loads(result.output) == [{"5 * 2": 10}]
# Check the request
request = httpx_mock.get_request()
assert str(request.url) == "https://example.com.json?sql=hello&_shape=objects"
if with_token:
assert request.headers["authorization"] == "Bearer xyz"
else:
assert "authorization" not in request.headers
def test_aliases(mocker, tmpdir, httpx_mock):
mocker.patch("dclient.cli.get_config_dir", return_value=pathlib.Path(tmpdir))

67
tests/test_utils.py Normal file
View file

@ -0,0 +1,67 @@
from dclient.utils import token_for_url, url_matches_prefix
import pytest
@pytest.mark.parametrize(
"url,prefix_url,expected",
(
("https://example.com/foo/bar", "https://example.com/foo", True),
("https://example.com/foo/bar2", "https://example.com/foo/bar", False),
("https://example.com/foo/bar/baz", "https://example.com/foo/bar", True),
("https://example.com/foo/bar/baz", "https://example.com/foo", True),
("https://example.com/foo.json", "https://example.com/foo", True),
# different scheme
(
"http://example.com/foo/bar",
"https://example.com/foo",
False,
),
# different netloc
(
"https://example.org/foo/bar",
"https://example.com/foo",
False,
),
# exactly the same
("https://example.com/foo", "https://example.com/foo", True),
# trailing '/'
(
"https://example.com/foo/bar",
"https://example.com/foo/bar/",
False,
),
(
"https://example.com/foo/bar/baz",
"https://example.com/foo/bar/",
True,
),
),
)
def test_url_matches_prefix(url, prefix_url, expected):
assert url_matches_prefix(url, prefix_url) == expected
@pytest.mark.parametrize(
"url,tokens,expected",
(
("https://foo.com/bar", {"https://foo.com": "foo"}, "foo"),
("https://foo.com/bar", {"https://foo.com/baz": "baz"}, None),
(
"https://foo.com/bar",
{"https://foo.com": "foo", "https://foo.com/bar": "bar"},
"bar",
),
(
"https://foo.com/bar/baz",
{
"https://foo.com": "foo",
"https://foo.com/bar/baz": "baz",
"https://foo.com/bar": "bar",
},
"baz",
),
),
)
def test_token_for_url(url, tokens, expected):
# Should always return longest matching of the available options
assert token_for_url(url, tokens) == expected