diff --git a/tests/integration/test_status.py b/tests/integration/test_status.py index 61f8e91..3daf65e 100644 --- a/tests/integration/test_status.py +++ b/tests/integration/test_status.py @@ -1,3 +1,4 @@ +import json import time import pytest @@ -5,7 +6,7 @@ from toot import api from toot.exceptions import NotFoundError -def test_delete_status(app, user, run): +def test_delete(app, user, run): status = api.post_status(app, user, "foo").json() out = run("delete", status["id"]) @@ -15,6 +16,17 @@ def test_delete_status(app, user, run): api.fetch_status(app, user, status["id"]) +def test_delete_json(app, user, run): + status = api.post_status(app, user, "foo").json() + + out = run("delete", status["id"], "--json") + result = json.loads(out) + assert result["id"] == status["id"] + + with pytest.raises(NotFoundError): + api.fetch_status(app, user, status["id"]) + + def test_favourite(app, user, run): status = api.post_status(app, user, "foo").json() assert not status["favourited"] @@ -35,6 +47,23 @@ def test_favourite(app, user, run): assert not status["favourited"] +def test_favourite_json(app, user, run): + status = api.post_status(app, user, "foo").json() + assert not status["favourited"] + + out = run("favourite", status["id"], "--json") + result = json.loads(out) + + assert result["id"] == status["id"] + assert result["favourited"] is True + + out = run("unfavourite", status["id"], "--json") + result = json.loads(out) + + assert result["id"] == status["id"] + assert result["favourited"] is False + + def test_reblog(app, user, run): status = api.post_status(app, user, "foo").json() assert not status["reblogged"] @@ -55,6 +84,27 @@ def test_reblog(app, user, run): assert not status["reblogged"] +def test_reblog_json(app, user, run): + status = api.post_status(app, user, "foo").json() + assert not status["reblogged"] + + out = run("reblog", status["id"], "--json") + result = json.loads(out) + + assert result["reblogged"] is True + assert result["reblog"]["id"] == status["id"] + + out = run("reblogged_by", status["id"], "--json") + [reblog] = json.loads(out) + assert reblog["acct"] == user.username + + out = run("unreblog", status["id"], "--json") + result = json.loads(out) + + assert result["reblogged"] is False + assert result["reblog"] is None + + def test_pin(app, user, run): status = api.post_status(app, user, "foo").json() assert not status["pinned"] @@ -72,6 +122,23 @@ def test_pin(app, user, run): assert not status["pinned"] +def test_pin_json(app, user, run): + status = api.post_status(app, user, "foo").json() + assert not status["pinned"] + + out = run("pin", status["id"], "--json") + result = json.loads(out) + + assert result["pinned"] is True + assert result["id"] == status["id"] + + out = run("unpin", status["id"], "--json") + result = json.loads(out) + + assert result["pinned"] is False + assert result["id"] == status["id"] + + def test_bookmark(app, user, run): status = api.post_status(app, user, "foo").json() assert not status["bookmarked"] @@ -87,3 +154,20 @@ def test_bookmark(app, user, run): status = api.fetch_status(app, user, status["id"]).json() assert not status["bookmarked"] + + +def test_bookmark_json(app, user, run): + status = api.post_status(app, user, "foo").json() + assert not status["bookmarked"] + + out = run("bookmark", status["id"], "--json") + result = json.loads(out) + + assert result["id"] == status["id"] + assert result["bookmarked"] is True + + out = run("unbookmark", status["id"], "--json") + result = json.loads(out) + + assert result["id"] == status["id"] + assert result["bookmarked"] is False diff --git a/tests/test_console.py b/tests/test_console.py index 72a114b..d9859df 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -196,36 +196,6 @@ def test_timeline_with_re(mock_get, monkeypatch, capsys): assert err == "" -@mock.patch('toot.http.get') -def test_reblogged_by(mock_get, monkeypatch, capsys): - mock_get.return_value = MockResponse([{ - 'display_name': 'Terry Bozzio', - 'acct': 'bozzio@drummers.social', - }, { - 'display_name': 'Dweezil', - 'acct': 'dweezil@zappafamily.social', - }]) - - console.run_command(app, user, 'reblogged_by', ['111111111111111111']) - - calls = [ - mock.call(app, user, '/api/v1/statuses/111111111111111111/reblogged_by'), - ] - mock_get.assert_has_calls(calls, any_order=False) - - out, err = capsys.readouterr() - - # Display order - expected = "\n".join([ - "Terry Bozzio", - " @bozzio@drummers.social", - "Dweezil", - " @dweezil@zappafamily.social", - "", - ]) - assert out == expected - - @mock.patch('toot.http.post') def test_upload(mock_post, capsys): mock_post.return_value = MockResponse({ diff --git a/toot/api.py b/toot/api.py index 829e53d..2158b13 100644 --- a/toot/api.py +++ b/toot/api.py @@ -43,9 +43,9 @@ def _account_action(app, user, account, action): return http.post(app, user, url).json() -def _status_action(app, user, status_id, action, data=None): +def _status_action(app, user, status_id, action, data=None) -> Response: url = f"/api/v1/statuses/{status_id}/{action}" - return http.post(app, user, url, data=data).json() + return http.post(app, user, url, data=data) def _tag_action(app, user, tag_name, action): @@ -301,9 +301,9 @@ def context(app, user, status_id) -> Response: return http.get(app, user, url) -def reblogged_by(app, user, status_id): +def reblogged_by(app, user, status_id) -> Response: url = f"/api/v1/statuses/{status_id}/reblogged_by" - return http.get(app, user, url).json() + return http.get(app, user, url) def _get_next_path(headers): diff --git a/toot/commands.py b/toot/commands.py index c2b3d43..285258b 100644 --- a/toot/commands.py +++ b/toot/commands.py @@ -10,7 +10,7 @@ from toot.auth import login_interactive, login_browser_interactive, create_app_i from toot.entities import Account, Instance, Notification, Status, from_dict from toot.exceptions import ApiError, ConsoleError from toot.output import (print_lists, print_out, print_instance, print_account, print_acct_list, - print_search_results, print_status, print_timeline, print_notifications, print_tag_list, + print_search_results, print_status, print_table, print_timeline, print_notifications, print_tag_list, print_list_accounts, print_user_list) from toot.utils import args_get_instance, delete_tmp_status_file, editor_input, multiline_input, EOF_KEY from toot.utils.datetime import parse_datetime @@ -212,48 +212,75 @@ def _wait_until_processed(app, user, media, start_time, timeout): def delete(app, user, args): - api.delete_status(app, user, args.status_id) - print_out("✓ Status deleted") + response = api.delete_status(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status deleted") def favourite(app, user, args): - api.favourite(app, user, args.status_id) - print_out("✓ Status favourited") + response = api.favourite(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status favourited") def unfavourite(app, user, args): - api.unfavourite(app, user, args.status_id) - print_out("✓ Status unfavourited") + response = api.unfavourite(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status unfavourited") def reblog(app, user, args): - api.reblog(app, user, args.status_id, visibility=args.visibility) - print_out("✓ Status reblogged") + response = api.reblog(app, user, args.status_id, visibility=args.visibility) + if args.json: + print(response.text) + else: + print_out("✓ Status reblogged") def unreblog(app, user, args): - api.unreblog(app, user, args.status_id) - print_out("✓ Status unreblogged") + response = api.unreblog(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status unreblogged") def pin(app, user, args): - api.pin(app, user, args.status_id) - print_out("✓ Status pinned") + response = api.pin(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status pinned") def unpin(app, user, args): - api.unpin(app, user, args.status_id) - print_out("✓ Status unpinned") + response = api.unpin(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status unpinned") def bookmark(app, user, args): - api.bookmark(app, user, args.status_id) - print_out("✓ Status bookmarked") + response = api.bookmark(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status bookmarked") def unbookmark(app, user, args): - api.unbookmark(app, user, args.status_id) - print_out("✓ Status unbookmarked") + response = api.unbookmark(app, user, args.status_id) + if args.json: + print(response.text) + else: + print_out("✓ Status unbookmarked") def bookmarks(app, user, args): @@ -261,8 +288,14 @@ def bookmarks(app, user, args): def reblogged_by(app, user, args): - for account in api.reblogged_by(app, user, args.status_id): - print_out("{}\n @{}".format(account['display_name'], account['acct'])) + response = api.reblogged_by(app, user, args.status_id) + + if args.json: + print(response.text) + else: + headers = ["Account", "Display name"] + rows = [[a["acct"], a["display_name"]] for a in response.json()] + print_table(headers, rows) def auth(app, user, args): diff --git a/toot/console.py b/toot/console.py index 1916941..9f74557 100644 --- a/toot/console.py +++ b/toot/console.py @@ -608,61 +608,61 @@ STATUS_COMMANDS = [ Command( name="delete", description="Delete a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="favourite", description="Favourite a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="unfavourite", description="Unfavourite a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="reblog", description="Reblog a status", - arguments=[status_id_arg, visibility_arg], + arguments=[status_id_arg, visibility_arg, json_arg], require_auth=True, ), Command( name="unreblog", description="Unreblog a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="reblogged_by", description="Show accounts that reblogged the status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=False, ), Command( name="pin", description="Pin a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="unpin", description="Unpin a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="bookmark", description="Bookmark a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), Command( name="unbookmark", description="Unbookmark a status", - arguments=[status_id_arg], + arguments=[status_id_arg, json_arg], require_auth=True, ), ]