toot/tests/test_console.py

295 wiersze
9.5 KiB
Python
Czysty Zwykły widok Historia

# -*- coding: utf-8 -*-
2017-04-15 12:46:22 +00:00
import pytest
import requests
2017-04-16 15:52:54 +00:00
import re
2017-04-15 12:46:22 +00:00
from requests import Request
2017-12-30 12:32:52 +00:00
from toot import console, User, App
from toot.exceptions import ConsoleError
2017-04-15 12:46:22 +00:00
from tests.utils import MockResponse, Expectations
2017-04-15 12:46:22 +00:00
app = App('habunek.com', 'https://habunek.com', 'foo', 'bar')
user = User('habunek.com', 'ivan@habunek.com', 'xxx')
2017-04-15 12:46:22 +00:00
2017-04-16 15:52:54 +00:00
def uncolorize(text):
"""Remove ANSI color sequences from a string"""
return re.sub(r'\x1b[^m]*m', '', text)
def test_print_usage(capsys):
2017-04-16 15:15:05 +00:00
console.print_usage()
out, err = capsys.readouterr()
2017-04-19 12:47:30 +00:00
assert "toot - a Mastodon CLI client" in out
2017-04-19 12:47:30 +00:00
def test_post_defaults(monkeypatch, capsys):
2017-04-15 12:46:22 +00:00
def mock_prepare(request):
assert request.method == 'POST'
assert request.url == 'https://habunek.com/api/v1/statuses'
assert request.headers == {'Authorization': 'Bearer xxx'}
2017-04-15 12:46:22 +00:00
assert request.data == {
'status': 'Hello world',
2017-04-15 12:46:22 +00:00
'visibility': 'public',
'media_ids[]': None,
}
def mock_send(*args, **kwargs):
2017-04-15 12:46:22 +00:00
return MockResponse({
'url': 'http://ivan.habunek.com/'
})
monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
monkeypatch.setattr(requests.Session, 'send', mock_send)
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'post', ['Hello world'])
out, err = capsys.readouterr()
assert "Toot posted" in out
2017-04-15 12:46:22 +00:00
2017-04-19 12:47:30 +00:00
def test_post_with_options(monkeypatch, capsys):
2017-04-15 12:46:22 +00:00
def mock_prepare(request):
assert request.method == 'POST'
assert request.url == 'https://habunek.com/api/v1/statuses'
assert request.headers == {'Authorization': 'Bearer xxx'}
2017-04-15 12:46:22 +00:00
assert request.data == {
'status': '"Hello world"',
'visibility': 'unlisted',
'media_ids[]': None,
}
def mock_send(*args, **kwargs):
2017-04-15 12:46:22 +00:00
return MockResponse({
'url': 'http://ivan.habunek.com/'
})
monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
monkeypatch.setattr(requests.Session, 'send', mock_send)
args = ['"Hello world"', '--visibility', 'unlisted']
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'post', args)
out, err = capsys.readouterr()
assert "Toot posted" in out
2017-04-19 12:47:30 +00:00
def test_post_invalid_visibility(monkeypatch, capsys):
args = ['Hello world', '--visibility', 'foo']
with pytest.raises(SystemExit):
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'post', args)
out, err = capsys.readouterr()
assert "invalid visibility value: 'foo'" in err
2017-04-19 12:47:30 +00:00
def test_post_invalid_media(monkeypatch, capsys):
args = ['Hello world', '--media', 'does_not_exist.jpg']
with pytest.raises(SystemExit):
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'post', args)
2017-04-15 12:46:22 +00:00
out, err = capsys.readouterr()
assert "can't open 'does_not_exist.jpg'" in err
2017-04-15 12:46:22 +00:00
def test_timeline(monkeypatch, capsys):
def mock_prepare(request):
assert request.url == 'https://habunek.com/api/v1/timelines/home'
assert request.headers == {'Authorization': 'Bearer xxx'}
assert request.params == {}
2017-04-15 12:46:22 +00:00
def mock_send(*args, **kwargs):
return MockResponse([{
'account': {
'display_name': 'Frank Zappa',
'username': 'fz'
},
'created_at': '2017-04-12T15:53:18.174Z',
'content': "<p>The computer can't tell you the emotional story. It can give you the exact mathematical design, but what's missing is the eyebrows.</p>",
'reblog': None,
}])
2017-04-15 12:46:22 +00:00
monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
monkeypatch.setattr(requests.Session, 'send', mock_send)
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'timeline', [])
out, err = capsys.readouterr()
assert "The computer can't tell you the emotional story." in out
assert "Frank Zappa @fz" in out
def test_upload(monkeypatch, capsys):
def mock_prepare(request):
assert request.method == 'POST'
assert request.url == 'https://habunek.com/api/v1/media'
assert request.headers == {'Authorization': 'Bearer xxx'}
assert request.files.get('file') is not None
def mock_send(*args, **kwargs):
return MockResponse({
'id': 123,
'url': 'https://bigfish.software/123/456',
'preview_url': 'https://bigfish.software/789/012',
'text_url': 'https://bigfish.software/345/678',
'type': 'image',
})
monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
monkeypatch.setattr(requests.Session, 'send', mock_send)
2017-04-15 12:46:22 +00:00
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'upload', [__file__])
2017-04-15 12:46:22 +00:00
out, err = capsys.readouterr()
assert "Uploading media" in out
assert __file__ in out
2017-04-16 13:07:27 +00:00
def test_search(monkeypatch, capsys):
def mock_prepare(request):
assert request.url == 'https://habunek.com/api/v1/search'
assert request.headers == {'Authorization': 'Bearer xxx'}
assert request.params == {
2017-04-16 13:07:27 +00:00
'q': 'freddy',
'resolve': False,
}
def mock_send(*args, **kwargs):
2017-04-16 13:07:27 +00:00
return MockResponse({
'hashtags': ['foo', 'bar', 'baz'],
'accounts': [{
'acct': 'thequeen',
'display_name': 'Freddy Mercury'
}, {
'acct': 'thequeen@other.instance',
'display_name': 'Mercury Freddy'
}],
'statuses': [],
})
monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
monkeypatch.setattr(requests.Session, 'send', mock_send)
2017-04-16 13:07:27 +00:00
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'search', ['freddy'])
2017-04-16 13:07:27 +00:00
out, err = capsys.readouterr()
assert "Hashtags:\n\033[32m#foo\033[0m, \033[32m#bar\033[0m, \033[32m#baz\033[0m" in out
assert "Accounts:" in out
assert "\033[32m@thequeen\033[0m Freddy Mercury" in out
assert "\033[32m@thequeen@other.instance\033[0m Mercury Freddy" in out
2017-04-16 15:15:05 +00:00
def test_follow(monkeypatch, capsys):
req1 = Request('GET', 'https://habunek.com/api/v1/accounts/search',
params={'q': 'blixa'},
headers={'Authorization': 'Bearer xxx'})
res1 = MockResponse([
{'id': 123, 'acct': 'blixa@other.acc'},
{'id': 321, 'acct': 'blixa'},
])
2017-04-16 15:15:05 +00:00
req2 = Request('POST', 'https://habunek.com/api/v1/accounts/321/follow',
headers={'Authorization': 'Bearer xxx'})
res2 = MockResponse()
2017-04-16 15:15:05 +00:00
expectations = Expectations([req1, req2], [res1, res2])
expectations.patch(monkeypatch)
2017-04-16 15:15:05 +00:00
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'follow', ['blixa'])
2017-04-16 15:15:05 +00:00
out, err = capsys.readouterr()
assert "You are now following blixa" in out
def test_follow_not_found(monkeypatch, capsys):
req = Request('GET', 'https://habunek.com/api/v1/accounts/search',
params={'q': 'blixa'}, headers={'Authorization': 'Bearer xxx'})
res = MockResponse()
2017-04-16 15:15:05 +00:00
expectations = Expectations([req], [res])
expectations.patch(monkeypatch)
2017-04-16 15:15:05 +00:00
2017-04-20 08:58:49 +00:00
with pytest.raises(ConsoleError) as ex:
console.run_command(app, user, 'follow', ['blixa'])
assert "Account not found" == str(ex.value)
2017-04-16 15:15:05 +00:00
def test_unfollow(monkeypatch, capsys):
req1 = Request('GET', 'https://habunek.com/api/v1/accounts/search',
params={'q': 'blixa'},
headers={'Authorization': 'Bearer xxx'})
res1 = MockResponse([
{'id': 123, 'acct': 'blixa@other.acc'},
{'id': 321, 'acct': 'blixa'},
])
2017-04-16 15:15:05 +00:00
req2 = Request('POST', 'https://habunek.com/api/v1/accounts/321/unfollow',
headers={'Authorization': 'Bearer xxx'})
res2 = MockResponse()
2017-04-16 15:15:05 +00:00
expectations = Expectations([req1, req2], [res1, res2])
expectations.patch(monkeypatch)
2017-04-16 15:15:05 +00:00
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'unfollow', ['blixa'])
2017-04-16 15:15:05 +00:00
out, err = capsys.readouterr()
assert "You are no longer following blixa" in out
def test_unfollow_not_found(monkeypatch, capsys):
req = Request('GET', 'https://habunek.com/api/v1/accounts/search',
params={'q': 'blixa'}, headers={'Authorization': 'Bearer xxx'})
res = MockResponse([])
2017-04-16 15:15:05 +00:00
expectations = Expectations([req], [res])
expectations.patch(monkeypatch)
2017-04-16 15:15:05 +00:00
2017-04-20 08:58:49 +00:00
with pytest.raises(ConsoleError) as ex:
console.run_command(app, user, 'unfollow', ['blixa'])
assert "Account not found" == str(ex.value)
2017-04-16 15:52:54 +00:00
def test_whoami(monkeypatch, capsys):
req = Request('GET', 'https://habunek.com/api/v1/accounts/verify_credentials',
headers={'Authorization': 'Bearer xxx'})
res = MockResponse({
'acct': 'ihabunek',
'avatar': 'https://files.mastodon.social/accounts/avatars/000/046/103/original/6a1304e135cac514.jpg?1491312434',
'avatar_static': 'https://files.mastodon.social/accounts/avatars/000/046/103/original/6a1304e135cac514.jpg?1491312434',
'created_at': '2017-04-04T13:23:09.777Z',
'display_name': 'Ivan Habunek',
'followers_count': 5,
'following_count': 9,
'header': '/headers/original/missing.png',
'header_static': '/headers/original/missing.png',
'id': 46103,
'locked': False,
'note': 'A developer.',
'statuses_count': 19,
'url': 'https://mastodon.social/@ihabunek',
'username': 'ihabunek'
})
expectations = Expectations([req], [res])
expectations.patch(monkeypatch)
2017-04-16 15:52:54 +00:00
2017-04-19 12:47:30 +00:00
console.run_command(app, user, 'whoami', [])
2017-04-16 15:52:54 +00:00
out, err = capsys.readouterr()
out = uncolorize(out)
assert "@ihabunek Ivan Habunek" in out
assert "A developer." in out
assert "https://mastodon.social/@ihabunek" in out
assert "ID: 46103" in out
assert "Since: 2017-04-04 @ 13:23:09" in out
assert "Followers: 5" in out
assert "Following: 9" in out
assert "Statuses: 19" in out