Ejemplo n.º 1
0
def test_timeline_with_re(mock_get, monkeypatch, capsys):
    mock_get.return_value = MockResponse([{
        'id':
        '111111111111111111',
        'account': {
            'display_name': 'Frank Zappa',
            'username': '******'
        },
        'created_at':
        '2017-04-12T15:53:18.174Z',
        'content':
        "<p>The computer can&apos;t tell you the emotional story. It can give you the exact mathematical design, but what's missing is the eyebrows.</p>",
        'reblog':
        None,
        'in_reply_to_id':
        '111111111111111110'
    }])

    console.run_command(app, user, 'timeline', [])

    mock_get.assert_called_once_with(app, user, '/api/v1/timelines/home')

    out, err = capsys.readouterr()
    assert "The computer can't tell you the emotional story." in out
    assert "but what's missing is the eyebrows." in out
    assert "Frank Zappa" in out
    assert "@fz" in out
    assert "id: 111111111111111111" in out
    assert "[RE]" in out
Ejemplo n.º 2
0
def test_post_with_options(monkeypatch, capsys):
    def mock_prepare(request):
        assert request.method == 'POST'
        assert request.url == 'https://habunek.com/api/v1/statuses'
        assert request.headers == {'Authorization': 'Bearer xxx'}
        assert request.data == {
            'status': '"Hello world"',
            'visibility': 'unlisted',
            'media_ids[]': None,
        }

    def mock_send(*args):
        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']

    console.run_command(app, user, 'post', args)

    out, err = capsys.readouterr()
    assert "Toot posted" in out
Ejemplo n.º 3
0
def test_search(mock_get, capsys):
    mock_get.return_value = MockResponse({
        'hashtags': ['foo', 'bar', 'baz'],
        'accounts': [{
            'acct': 'thequeen',
            'display_name': 'Freddy Mercury'
        }, {
            'acct': '*****@*****.**',
            'display_name': 'Mercury Freddy'
        }],
        'statuses': [],
    })

    console.run_command(app, user, 'search', ['freddy'])

    mock_get.assert_called_once_with(app, user, '/api/v1/search', {
        'q': 'freddy',
        'resolve': False,
    })

    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@[email protected]\033[0m Mercury Freddy" in out
Ejemplo n.º 4
0
def test_timeline(mock_get, monkeypatch, capsys):
    mock_get.return_value = MockResponse([{
        'id': '111111111111111111',
        'account': {
            'display_name': 'Frank Zappa 🎸',
            'acct': 'fz'
        },
        'created_at': '2017-04-12T15:53:18.174Z',
        'content':
        "<p>The computer can&apos;t tell you the emotional story. It can give you the exact mathematical design, but what's missing is the eyebrows.</p>",
        'reblog': None,
        'in_reply_to_id': None,
        'media_attachments': [],
    }])

    console.run_command(app, user, 'timeline', ['--once'])

    mock_get.assert_called_once_with(app, user,
                                     '/api/v1/timelines/home?limit=10', None)

    out, err = capsys.readouterr()
    lines = out.split("\n")

    assert "Frank Zappa 🎸" in lines[1]
    assert "@fz" in lines[1]
    assert "2017-04-12 15:53" in lines[1]

    assert (
        "The computer can't tell you the emotional story. It can give you the "
        "exact mathematical design, but\nwhat's missing is the eyebrows."
        in out)

    assert "111111111111111111" in lines[-3]

    assert err == ""
Ejemplo n.º 5
0
def test_search(monkeypatch, capsys):
    def mock_get(url, params, headers=None):
        assert url == 'https://habunek.com/api/v1/search'
        assert headers == {'Authorization': 'Bearer xxx'}
        assert params == {
            'q': 'freddy',
            'resolve': False,
        }

        return MockResponse({
            'hashtags': ['foo', 'bar', 'baz'],
            'accounts': [{
                'acct': 'thequeen',
                'display_name': 'Freddy Mercury'
            }, {
                'acct': '*****@*****.**',
                'display_name': 'Mercury Freddy'
            }],
            'statuses': [],
        })

    monkeypatch.setattr(requests, 'get', mock_get)

    console.run_command(app, user, 'search', ['freddy'])

    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@[email protected]\033[0m Mercury Freddy" in out
Ejemplo n.º 6
0
def test_unfollow(monkeypatch, capsys):
    def mock_get(url, params, headers):
        assert url == 'https://habunek.com/api/v1/search'
        assert params == {'q': 'blixa', 'resolve': False}
        assert headers == {'Authorization': 'Bearer xxx'}

        return MockResponse({
            'accounts': [
                {'id': 123, 'acct': '*****@*****.**'},
                {'id': 321, 'acct': 'blixa'},
            ]
        })

    def mock_prepare(request):
        assert request.url == 'https://habunek.com/api/v1/accounts/321/unfollow'

    def mock_send(*args, **kwargs):
        return MockResponse()

    monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
    monkeypatch.setattr(requests.Session, 'send', mock_send)
    monkeypatch.setattr(requests, 'get', mock_get)

    console.run_command(app, user, 'unfollow', ['blixa'])

    out, err = capsys.readouterr()
    assert "You are no longer following blixa" in out
Ejemplo n.º 7
0
def test_post_with_options(mock_post, mock_uuid, capsys):
    mock_uuid.return_value = MockUuid("up-the-irons")
    args = [
        'Hello world', '--visibility', 'unlisted', '--sensitive',
        '--spoiler-text', 'Spoiler!', '--reply-to', '123'
    ]

    mock_post.return_value = MockResponse(
        {'url': 'https://habunek.com/@ihabunek/1234567890'})

    console.run_command(app, user, 'post', args)

    mock_post.assert_called_once_with(
        app,
        user,
        '/api/v1/statuses', {
            'status': 'Hello world',
            'media_ids[]': None,
            'visibility': 'unlisted',
            'sensitive': "true",
            'spoiler_text': "Spoiler!",
            'in_reply_to_id': 123,
        },
        headers={"Idempotency-Key": "up-the-irons"})

    out, err = capsys.readouterr()
    assert 'Toot posted' in out
    assert 'https://habunek.com/@ihabunek/1234567890' in out
    assert not err
Ejemplo n.º 8
0
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 == {}

    def mock_send(*args, **kwargs):
        return MockResponse([{
            'account': {
                'display_name': 'Frank Zappa',
                'username': '******'
            },
            '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,
        }])

    monkeypatch.setattr(requests.Request, 'prepare', mock_prepare)
    monkeypatch.setattr(requests.Session, 'send', mock_send)

    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
Ejemplo n.º 9
0
def test_reblogged_by(mock_get, monkeypatch, capsys):
    mock_get.return_value = MockResponse([{
        'display_name': 'Terry Bozzio',
        'acct': '*****@*****.**',
    }, {
        'display_name': 'Dweezil',
        'acct': '*****@*****.**',
    }])

    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",
        " @[email protected]",
        "Dweezil",
        " @[email protected]",
        "",
    ])
    assert out == expected
Ejemplo n.º 10
0
def test_delete(mock_delete, capsys):
    console.run_command(app, user, 'delete', ['12321'])

    mock_delete.assert_called_once_with(app, user, '/api/v1/statuses/12321')

    out, err = capsys.readouterr()
    assert 'Status deleted' in out
    assert not err
Ejemplo n.º 11
0
def test_notifications_clear(mock_post, capsys):
    console.run_command(app, user, 'notifications', ['--clear'])
    out, err = capsys.readouterr()
    out = uncolorize(out)

    mock_post.assert_called_once_with(app, user, '/api/v1/notifications/clear')
    assert not err
    assert out == 'Cleared notifications\n'
Ejemplo n.º 12
0
def test_post_invalid_media(capsys):
    args = ['Hello world', '--media', 'does_not_exist.jpg']

    with pytest.raises(SystemExit):
        console.run_command(app, user, 'post', args)

    out, err = capsys.readouterr()
    assert "can't open 'does_not_exist.jpg'" in err
Ejemplo n.º 13
0
def test_post_invalid_visibility(capsys):
    args = ['Hello world', '--visibility', 'foo']

    with pytest.raises(SystemExit):
        console.run_command(app, user, 'post', args)

    out, err = capsys.readouterr()
    assert "invalid visibility value: 'foo'" in err
Ejemplo n.º 14
0
def test_follow_not_found(mock_get, capsys):
    mock_get.return_value = MockResponse()

    with pytest.raises(ConsoleError) as ex:
        console.run_command(app, user, 'follow', ['blixa'])

    mock_get.assert_called_once_with(app, user, '/api/v1/accounts/search',
                                     {'q': 'blixa'})
    assert "Account not found" == str(ex.value)
Ejemplo n.º 15
0
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([])

    expectations = Expectations([req], [res])
    expectations.patch(monkeypatch)

    with pytest.raises(ConsoleError) as ex:
        console.run_command(app, user, 'unfollow', ['blixa'])
    assert "Account not found" == str(ex.value)
Ejemplo n.º 16
0
def test_notifications_empty(mock_get, capsys):
    mock_get.return_value = MockResponse([])

    console.run_command(app, user, 'notifications', [])

    mock_get.assert_called_once_with(app, user, '/api/v1/notifications')

    out, err = capsys.readouterr()
    out = uncolorize(out)

    assert not err
    assert out == "No notification\n"
Ejemplo n.º 17
0
def test_unfollow_not_found(monkeypatch, capsys):
    def mock_get(url, params, headers):
        assert url == 'https://habunek.com/api/v1/search'
        assert params == {'q': 'blixa', 'resolve': False}
        assert headers == {'Authorization': 'Bearer xxx'}

        return MockResponse({
            'accounts': []
        })

    monkeypatch.setattr(requests, 'get', mock_get)

    with pytest.raises(ConsoleError) as ex:
        console.run_command(app, user, 'unfollow', ['blixa'])
    assert "Account not found" == str(ex.value)
Ejemplo n.º 18
0
def test_logout(mock_load, mock_save, capsys):
    mock_load.return_value = {
        "users": {
            "*****@*****.**": u("*****@*****.**"),
            "*****@*****.**": u("*****@*****.**"),
        },
        "active_user": "******",
    }

    console.run_command(app, user, "logout", ["*****@*****.**"])

    mock_save.assert_called_once_with({
        'users': {
            '*****@*****.**': u("*****@*****.**")
        },
        'active_user': None
    })

    out, err = capsys.readouterr()
    assert "✓ User [email protected] logged out" in out
Ejemplo n.º 19
0
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': '*****@*****.**'},
        {'id': 321, 'acct': 'blixa'},
    ])

    req2 = Request('POST', 'https://habunek.com/api/v1/accounts/321/unfollow',
                   headers={'Authorization': 'Bearer xxx'})
    res2 = MockResponse()

    expectations = Expectations([req1, req2], [res1, res2])
    expectations.patch(monkeypatch)

    console.run_command(app, user, 'unfollow', ['blixa'])

    out, err = capsys.readouterr()
    assert "You are no longer following blixa" in out
Ejemplo n.º 20
0
def test_upload(mock_post, capsys):
    mock_post.return_value = 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',
    })

    console.run_command(app, user, 'upload', [__file__])

    mock_post.call_count == 1

    args, kwargs = http.post.call_args
    assert args == (app, user, '/api/v1/media')
    assert isinstance(kwargs['files']['file'], io.BufferedReader)

    out, err = capsys.readouterr()
    assert "Uploading media" in out
    assert __file__ in out
Ejemplo n.º 21
0
def test_search(mock_get, capsys):
    mock_get.return_value = MockResponse({
        'hashtags': [
            {
                'history': [],
                'name': 'foo',
                'url': 'https://mastodon.social/tags/foo'
            },
            {
                'history': [],
                'name': 'bar',
                'url': 'https://mastodon.social/tags/bar'
            },
            {
                'history': [],
                'name': 'baz',
                'url': 'https://mastodon.social/tags/baz'
            },
        ],
        'accounts': [{
            'acct': 'thequeen',
            'display_name': 'Freddy Mercury'
        }, {
            'acct': '*****@*****.**',
            'display_name': 'Mercury Freddy'
        }],
        'statuses': [],
    })

    console.run_command(app, user, 'search', ['freddy'])

    mock_get.assert_called_once_with(app, user, '/api/v2/search', {
        'q': 'freddy',
        'resolve': False,
    })

    out, err = capsys.readouterr()
    assert "Hashtags:\n#foo, #bar, #baz" in out
    assert "Accounts:" in out
    assert "@thequeen Freddy Mercury" in out
    assert "@[email protected] Mercury Freddy" in out
Ejemplo n.º 22
0
def test_follow(mock_get, mock_post, capsys):
    mock_get.return_value = MockResponse([
        {
            'id': 123,
            'acct': '*****@*****.**'
        },
        {
            'id': 321,
            'acct': 'blixa'
        },
    ])
    mock_post.return_value = MockResponse()

    console.run_command(app, user, 'follow', ['blixa'])

    mock_get.assert_called_once_with(app, user, '/api/v1/accounts/search',
                                     {'q': 'blixa'})
    mock_post.assert_called_once_with(app, user, '/api/v1/accounts/321/follow')

    out, err = capsys.readouterr()
    assert "You are now following blixa" in out
Ejemplo n.º 23
0
def test_activate(mock_load, mock_save, capsys):
    mock_load.return_value = {
        "users": {
            "*****@*****.**": u("*****@*****.**"),
            "*****@*****.**": u("*****@*****.**"),
        },
        "active_user": "******",
    }

    console.run_command(app, user, "activate", ["*****@*****.**"])

    mock_save.assert_called_once_with({
        'users': {
            "*****@*****.**": u("*****@*****.**"),
            '*****@*****.**': u("*****@*****.**")
        },
        'active_user': "******"
    })

    out, err = capsys.readouterr()
    assert "✓ User [email protected] active" in out
Ejemplo n.º 24
0
def test_whoami(monkeypatch, capsys):
    def mock_get(url, params, headers=None):
        assert url == 'https://habunek.com/api/v1/accounts/verify_credentials'
        assert headers == {'Authorization': 'Bearer xxx'}
        assert params is None

        return 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': '******'
        })

    monkeypatch.setattr(requests, 'get', mock_get)

    console.run_command(app, user, 'whoami', [])

    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
Ejemplo n.º 25
0
def test_logout(monkeypatch, capsys):
    def mock_load():
        return {
            "users": {
                "*****@*****.**": u("*****@*****.**"),
                "*****@*****.**": u("*****@*****.**"),
            },
            "active_user": "******",
        }

    def mock_save(config):
        assert config["users"] == {
            "*****@*****.**": u("*****@*****.**")
        }
        assert config["active_user"] is None

    monkeypatch.setattr(config, "load_config", mock_load)
    monkeypatch.setattr(config, "save_config", mock_save)

    console.run_command(None, None, "logout", ["*****@*****.**"])

    out, err = capsys.readouterr()
    assert "✓ User [email protected] logged out" in out
Ejemplo n.º 26
0
def test_post_defaults(mock_post, mock_uuid, capsys):
    mock_uuid.return_value = MockUuid("rock-on")
    mock_post.return_value = MockResponse(
        {'url': 'https://habunek.com/@ihabunek/1234567890'})

    console.run_command(app, user, 'post', ['Hello world'])

    mock_post.assert_called_once_with(app,
                                      user,
                                      '/api/v1/statuses', {
                                          'status': 'Hello world',
                                          'visibility': 'public',
                                          'media_ids[]': None,
                                          'sensitive': "false",
                                          'spoiler_text': None,
                                          'in_reply_to_id': None,
                                      },
                                      headers={"Idempotency-Key": "rock-on"})

    out, err = capsys.readouterr()
    assert 'Toot posted' in out
    assert 'https://habunek.com/@ihabunek/1234567890' in out
    assert not err
Ejemplo n.º 27
0
def test_whoami(mock_get, capsys):
    mock_get.return_value = 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': '******'
    })

    console.run_command(app, user, 'whoami', [])

    mock_get.assert_called_once_with(app, user,
                                     '/api/v1/accounts/verify_credentials')

    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
Ejemplo n.º 28
0
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):
        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)

    console.run_command(app, user, 'upload', [__file__])

    out, err = capsys.readouterr()
    assert "Uploading media" in out
    assert __file__ in out
Ejemplo n.º 29
0
def test_notifications(mock_get, capsys):
    mock_get.return_value = MockResponse([{
        'id': '1',
        'type': 'follow',
        'created_at': '2019-02-16T07:01:20.714Z',
        'account': {
            'display_name': 'Frank Zappa',
            'acct': '*****@*****.**',
        },
    }, {
        'id': '2',
        'type': 'mention',
        'created_at': '2017-01-12T12:12:12.0Z',
        'account': {
            'display_name': 'Dweezil Zappa',
            'acct': '*****@*****.**',
        },
        'status': {
            'id': '111111111111111111',
            'account': {
                'display_name': 'Dweezil Zappa',
                'acct': '*****@*****.**',
            },
            'created_at': '2017-04-12T15:53:18.174Z',
            'content': "<p>We still have fans in 2017 @fan123</p>",
            'reblog': None,
            'in_reply_to_id': None,
            'media_attachments': [],
        },
    }, {
        'id': '3',
        'type': 'reblog',
        'created_at': '1983-11-03T03:03:03.333Z',
        'account': {
            'display_name': 'Terry Bozzio',
            'acct': '*****@*****.**',
        },
        'status': {
            'id': '1234',
            'account': {
                'display_name': 'Zappa Fan',
                'acct': '*****@*****.**'
            },
            'created_at': '1983-11-04T15:53:18.174Z',
            'content': "<p>The Black Page, a masterpiece</p>",
            'reblog': None,
            'in_reply_to_id': None,
            'media_attachments': [],
        },
    }, {
        'id': '4',
        'type': 'favourite',
        'created_at': '1983-12-13T01:02:03.444Z',
        'account': {
            'display_name': 'Zappa Old Fan',
            'acct': '*****@*****.**',
        },
        'status': {
            'id': '1234',
            'account': {
                'display_name': 'Zappa Fan',
                'acct': '*****@*****.**'
            },
            'created_at': '1983-11-04T15:53:18.174Z',
            'content': "<p>The Black Page, a masterpiece</p>",
            'reblog': None,
            'in_reply_to_id': None,
            'media_attachments': [],
        },
    }])

    console.run_command(app, user, 'notifications', [])

    mock_get.assert_called_once_with(app, user, '/api/v1/notifications')

    out, err = capsys.readouterr()
    out = uncolorize(out)

    width = 100
    assert not err
    assert out == "\n".join([
        "─" * width,
        "Frank Zappa @[email protected] now follows you",
        "─" * width,
        "Dweezil Zappa @[email protected] mentioned you in",
        "Dweezil Zappa @[email protected]                                                 2017-04-12 15:53",
        "",
        "We still have fans in 2017 @fan123",
        "",
        "ID 111111111111111111  ",
        "─" * width,
        "Terry Bozzio @[email protected] reblogged your status",
        "Zappa Fan @[email protected]                                                 1983-11-04 15:53",
        "",
        "The Black Page, a masterpiece",
        "",
        "ID 1234  ",
        "─" * width,
        "Zappa Old Fan @[email protected] favourited your status",
        "Zappa Fan @[email protected]                                                 1983-11-04 15:53",
        "",
        "The Black Page, a masterpiece",
        "",
        "ID 1234  ",
        "─" * width,
        "",
    ])
Ejemplo n.º 30
0
def test_thread(mock_get, monkeypatch, capsys):
    mock_get.side_effect = [
        MockResponse({
            'id': '111111111111111111',
            'account': {
                'display_name': 'Frank Zappa',
                'acct': 'fz'
            },
            'created_at': '2017-04-12T15:53:18.174Z',
            'content': "my response in the middle",
            'reblog': None,
            'in_reply_to_id': '111111111111111110',
            'media_attachments': [],
        }),
        MockResponse({
            'ancestors': [{
                'id': '111111111111111110',
                'account': {
                    'display_name': 'Frank Zappa',
                    'acct': 'fz'
                },
                'created_at': '2017-04-12T15:53:18.174Z',
                'content': "original content",
                'media_attachments': [],
                'reblog': None,
                'in_reply_to_id': None
            }],
            'descendants': [{
                'id': '111111111111111112',
                'account': {
                    'display_name': 'Frank Zappa',
                    'acct': 'fz'
                },
                'created_at': '2017-04-12T15:53:18.174Z',
                'content': "response message",
                'media_attachments': [],
                'reblog': None,
                'in_reply_to_id': '111111111111111111'
            }],
        }),
    ]

    console.run_command(app, user, 'thread', ['111111111111111111'])

    calls = [
        mock.call(app, user, '/api/v1/statuses/111111111111111111'),
        mock.call(app, user, '/api/v1/statuses/111111111111111111/context'),
    ]
    mock_get.assert_has_calls(calls, any_order=False)

    out, err = capsys.readouterr()

    assert not err

    # Display order
    assert out.index('original content') < out.index(
        'my response in the middle')
    assert out.index('my response in the middle') < out.index(
        'response message')

    assert "original content" in out
    assert "my response in the middle" in out
    assert "response message" in out
    assert "Frank Zappa" in out
    assert "@fz" in out
    assert "111111111111111111" in out
    assert "In reply to" in out