Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ihabunek committed Nov 27, 2023
1 parent c413679 commit 37d6368
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 112 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
},
entry_points={
'console_scripts': [
'toot=toot.console:main',
'toot=toot.cli:cli',
],
}
)
22 changes: 11 additions & 11 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import pytest
import uuid

from click.testing import CliRunner, Result
from pathlib import Path
from toot import api, App, User
from toot.cli import Context
from toot.console import run_command
from toot.exceptions import ApiError, ConsoleError
from toot.output import print_out
Expand Down Expand Up @@ -105,19 +107,17 @@ def friend_id(app, user, friend):
return api.find_account(app, user, friend.username)["id"]


@pytest.fixture(scope="session", autouse=True)
def testing_env():
os.environ["TOOT_TESTING"] = "true"


@pytest.fixture
def run(app, user, capsys):
def _run(command, *params, as_user=None):
# The try/catch duplicates logic from console.main to convert exceptions
# to printed error messages. TODO: could be deduped
try:
run_command(app, as_user or user, command, params or [])
except (ConsoleError, ApiError) as e:
print_out(str(e))

out, err = capsys.readouterr()
assert err == ""
return strip_ansi(out)
def _run(command, *params, as_user=None) -> Result:
runner = CliRunner()
ctx = Context(app, as_user or user)
return runner.invoke(command, params, obj=ctx)
return _run


Expand Down
199 changes: 105 additions & 94 deletions tests/integration/test_read.py
Original file line number Diff line number Diff line change
@@ -1,146 +1,157 @@
import json
from pprint import pprint
from click.testing import CliRunner, Result
import pytest
import re

from toot import api
from toot import api, cli
from toot.cli import Context
from toot.entities import Account, from_dict_list
from toot.exceptions import ConsoleError
from uuid import uuid4


def invoke(app, user, command, *args) -> Result:
ctx = Context(app, user)
runner = CliRunner()
return runner.invoke(command, args, obj=ctx)


def test_instance(app, run):
out = run("instance", "--disable-https")
assert "Mastodon" in out
assert app.instance in out
assert "running Mastodon" in out
result = run(cli.instance)
assert result.exit_code == 0

assert "Mastodon" in result.stdout
assert app.instance in result.stdout
assert "running Mastodon" in result.stdout


def test_instance_json(app, run):
out = run("instance", "--json")
data = json.loads(out)
result = run(cli.instance, "--json")
assert result.exit_code == 0

data = json.loads(result.stdout)
assert data["title"] is not None
assert data["description"] is not None
assert data["version"] is not None


def test_instance_anon(app, run_anon, base_url):
out = run_anon("instance", base_url)
assert "Mastodon" in out
assert app.instance in out
assert "running Mastodon" in out
# def test_instance_anon(app, run_anon, base_url):
# out = run_anon("instance", base_url)
# assert "Mastodon" in out
# assert app.instance in out
# assert "running Mastodon" in out

# Need to specify the instance name when running anon
with pytest.raises(ConsoleError) as exc:
run_anon("instance")
assert str(exc.value) == "Please specify an instance."
# # Need to specify the instance name when running anon
# with pytest.raises(ConsoleError) as exc:
# run_anon("instance")
# assert str(exc.value) == "Please specify an instance."


def test_whoami(user, run):
out = run("whoami")
# TODO: test other fields once updating account is supported
assert f"@{user.username}" in out
# def test_whoami(user, run):
# out = run("whoami")
# # TODO: test other fields once updating account is supported
# assert f"@{user.username}" in out


def test_whois(app, friend, run):
variants = [
friend.username,
f"@{friend.username}",
f"{friend.username}@{app.instance}",
f"@{friend.username}@{app.instance}",
]
# def test_whois(app, friend, run):
# variants = [
# friend.username,
# f"@{friend.username}",
# f"{friend.username}@{app.instance}",
# f"@{friend.username}@{app.instance}",
# ]

for username in variants:
out = run("whois", username)
assert f"@{friend.username}" in out
# for username in variants:
# out = run("whois", username)
# assert f"@{friend.username}" in out


def test_search_account(friend, run):
out = run("search", friend.username)
assert out == f"Accounts:\n* @{friend.username}"
# def test_search_account(friend, run):
# out = run("search", friend.username)
# assert out == f"Accounts:\n* @{friend.username}"


def test_search_account_json(friend, run_json):
out = run_json("search", friend.username, "--json")
[account] = from_dict_list(Account, out["accounts"])
assert account.acct == friend.username
# def test_search_account_json(friend, run_json):
# out = run_json("search", friend.username, "--json")
# [account] = from_dict_list(Account, out["accounts"])
# assert account.acct == friend.username


def test_search_hashtag(app, user, run):
api.post_status(app, user, "#hashtag_x")
api.post_status(app, user, "#hashtag_y")
api.post_status(app, user, "#hashtag_z")
# def test_search_hashtag(app, user, run):
# api.post_status(app, user, "#hashtag_x")
# api.post_status(app, user, "#hashtag_y")
# api.post_status(app, user, "#hashtag_z")

out = run("search", "#hashtag")
assert out == "Hashtags:\n#hashtag_x, #hashtag_y, #hashtag_z"
# out = run("search", "#hashtag")
# assert out == "Hashtags:\n#hashtag_x, #hashtag_y, #hashtag_z"


def test_search_hashtag_json(app, user, run_json):
api.post_status(app, user, "#hashtag_x")
api.post_status(app, user, "#hashtag_y")
api.post_status(app, user, "#hashtag_z")
# def test_search_hashtag_json(app, user, run_json):
# api.post_status(app, user, "#hashtag_x")
# api.post_status(app, user, "#hashtag_y")
# api.post_status(app, user, "#hashtag_z")

out = run_json("search", "#hashtag", "--json")
[h1, h2, h3] = sorted(out["hashtags"], key=lambda h: h["name"])
# out = run_json("search", "#hashtag", "--json")
# [h1, h2, h3] = sorted(out["hashtags"], key=lambda h: h["name"])

assert h1["name"] == "hashtag_x"
assert h2["name"] == "hashtag_y"
assert h3["name"] == "hashtag_z"
# assert h1["name"] == "hashtag_x"
# assert h2["name"] == "hashtag_y"
# assert h3["name"] == "hashtag_z"


def test_tags(run, base_url):
out = run("tags_followed")
assert out == "You're not following any hashtags."
# def test_tags(run, base_url):
# out = run("tags_followed")
# assert out == "You're not following any hashtags."

out = run("tags_follow", "foo")
assert out == "✓ You are now following #foo"
# out = run("tags_follow", "foo")
# assert out == "✓ You are now following #foo"

out = run("tags_followed")
assert out == f"* #foo\t{base_url}/tags/foo"
# out = run("tags_followed")
# assert out == f"* #foo\t{base_url}/tags/foo"

out = run("tags_follow", "bar")
assert out == "✓ You are now following #bar"
# out = run("tags_follow", "bar")
# assert out == "✓ You are now following #bar"

out = run("tags_followed")
assert out == "\n".join([
f"* #bar\t{base_url}/tags/bar",
f"* #foo\t{base_url}/tags/foo",
])
# out = run("tags_followed")
# assert out == "\n".join([
# f"* #bar\t{base_url}/tags/bar",
# f"* #foo\t{base_url}/tags/foo",
# ])

out = run("tags_unfollow", "foo")
assert out == "✓ You are no longer following #foo"
# out = run("tags_unfollow", "foo")
# assert out == "✓ You are no longer following #foo"

out = run("tags_followed")
assert out == f"* #bar\t{base_url}/tags/bar"
# out = run("tags_followed")
# assert out == f"* #bar\t{base_url}/tags/bar"


def test_status(app, user, run):
uuid = str(uuid4())
response = api.post_status(app, user, uuid).json()
# def test_status(app, user, run):
# uuid = str(uuid4())
# response = api.post_status(app, user, uuid).json()

out = run("status", response["id"])
assert uuid in out
assert user.username in out
assert response["id"] in out
# out = run("status", response["id"])
# assert uuid in out
# assert user.username in out
# assert response["id"] in out


def test_thread(app, user, run):
uuid = str(uuid4())
s1 = api.post_status(app, user, uuid + "1").json()
s2 = api.post_status(app, user, uuid + "2", in_reply_to_id=s1["id"]).json()
s3 = api.post_status(app, user, uuid + "3", in_reply_to_id=s2["id"]).json()
# def test_thread(app, user, run):
# uuid = str(uuid4())
# s1 = api.post_status(app, user, uuid + "1").json()
# s2 = api.post_status(app, user, uuid + "2", in_reply_to_id=s1["id"]).json()
# s3 = api.post_status(app, user, uuid + "3", in_reply_to_id=s2["id"]).json()

for status in [s1, s2, s3]:
out = run("thread", status["id"])
bits = re.split(r"─+", out)
bits = [b for b in bits if b]
# for status in [s1, s2, s3]:
# out = run("thread", status["id"])
# bits = re.split(r"─+", out)
# bits = [b for b in bits if b]

assert len(bits) == 3
# assert len(bits) == 3

assert s1["id"] in bits[0]
assert s2["id"] in bits[1]
assert s3["id"] in bits[2]
# assert s1["id"] in bits[0]
# assert s2["id"] in bits[1]
# assert s3["id"] in bits[2]

assert f"{uuid}1" in bits[0]
assert f"{uuid}2" in bits[1]
assert f"{uuid}3" in bits[2]
# assert f"{uuid}1" in bits[0]
# assert f"{uuid}2" in bits[1]
# assert f"{uuid}3" in bits[2]
14 changes: 8 additions & 6 deletions toot/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import os
import sys
import click
import json as pyjson
Expand All @@ -10,6 +11,7 @@
from toot.output import print_account, print_instance, print_search_results
from typing import Callable, Concatenate, NamedTuple, Optional, ParamSpec, TypeVar


# Tweak the Click context
# https://click.palletsprojects.com/en/8.1.x/api/#context
CONTEXT = dict(
Expand All @@ -26,11 +28,11 @@

# Data object to add to Click context
class Context(NamedTuple):
app: Optional[App]
user: Optional[User]
color: bool
debug: bool
quiet: bool
app: Optional[App] = None
user: Optional[User] = None
color: bool = False
debug: bool = False
quiet: bool = False


P = ParamSpec("P")
Expand Down Expand Up @@ -61,7 +63,7 @@ def wrapped(*args: P.args, **kwargs: P.kwargs) -> R:
@click.option("--color/--no-color", default=sys.stdout.isatty(), help="Use ANSI color in output")
@click.option("--quiet/--no-quiet", default=False, help="Don't print anything to stdout")
@click.pass_context
def cli(ctx, color, debug, quiet):
def cli(ctx, color, debug, quiet, app=None, user=None):
"""Toot is a Mastodon CLI"""
user, app = config.get_active_user_app()
ctx.obj = Context(app, user, color, debug, quiet)
Expand Down

0 comments on commit 37d6368

Please sign in to comment.