async def test_unset(test_db): with database() as (conn, cursor): cursor.execute(""" INSERT INTO lastfm (user, listener, lastfm) VALUES ('azuline', 'DiscordListener', 'azulfm') """) conn.commit() await unset.call( Message( bot=None, listener=Mock( is_authed=AsyncMock(return_value="azuline"), spec=DiscordListener, __str__=lambda *a: "DiscordListener", ), target="#chan", author="azul", contents="", private=True, )) with database() as (conn, cursor): cursor.execute(""" SELECT lastfm FROM lastfm WHERE user = '******' and listener = 'DiscordListener' """) assert not cursor.fetchone()
async def test_tell_handler(): with patch("chitanda.modules.tell._fetch_tells") as fetch: with patch("chitanda.modules.tell._delete_tell") as delete: fetch.return_value = [ { "time": "2019-01-01T12:34:56", "sender": "azul", "message": "hi", "id": 1, }, { "time": "2019-01-02T12:34:56", "sender": "azul", "message": "hi again", "id": 2, }, ] responses = [ r async for r in tell_handler( Message(None, None, None, "newuser", None, False) ) ] assert responses == [ "newuser: On Jan 01, 12:34:56, azul said: hi", "newuser: On Jan 02, 12:34:56, azul said: hi again", ] assert delete.call_args_list == [call(1), call(2)]
async def test_aliases_discord(monkeypatch): monkeypatch.setattr( 'chitanda.modules.aliases.config', { 'trigger_character': '.', 'aliases': { 'global': { 'a': 'apples', 'b': 'bananas' } }, }, ) response = [ r async for r in call( Message( bot=None, listener=Mock(spec=DiscordListener), target=None, author='azul', contents='', private=False, )) ][0] assert response['message'].title == 'Aliases' assert response['message'].fields[0].name == '.a' assert response['message'].fields[0].value == '.apples' assert response['message'].fields[1].name == '.b' assert response['message'].fields[1].value == '.bananas'
async def test_delete_quote(test_db): with patch("chitanda.modules.quotes.delete.fetch.fetch_quotes") as f: f.return_value = [] with database() as (conn, cursor): cursor.execute(""" INSERT INTO quotes (id, channel, listener, quote, adder) VALUES (1, '#chan', 'DiscordListener', 'hi', 'azul'), (2, '#chan', 'DiscordListener', 'hi again', 'azul'), (1, '#notchan', 'DiscordListener', 'bye', 'azul'), (3, '#chan', 'IRCListener', 'bye again', 'azul') """) conn.commit() async for r in delete.call( Message( bot=None, listener=Mock( is_admin=AsyncMock(return_value=True), spec=DiscordListener, __str__=lambda *a: "DiscordListener", ), target="#chan", author="azul", contents="1 2 3", private=False, )): pass cursor.execute("SELECT COUNT(1) FROM quotes") assert 2 == cursor.fetchone()[0]
def test_parse_command_trigger_match(monkeypatch): monkeypatch.setattr('chitanda.util.config', TEST_PARSE_CONFIG) cmd = Mock(__name__='henlo', call=Mock(return_value=123)) bot = Mock(commands={'henlo ': cmd}) message = Message(bot, 'TestListener', 2, 3, '.not henlo', 5) with pytest.raises(NoCommandFound): message.call_command()
async def test_help(applicable_listener, monkeypatch): monkeypatch.setattr( 'chitanda.modules.help.config', {'trigger_character': '.'} ) applicable_listener.return_value = True bot = Mock(commands={'aaa': Mock(call=a), 'b': Mock(call=b)}) response = [ r async for r in call( Message( bot=bot, listener=None, target='azul', author='azul', contents='', private=False, ) ) ] assert response == [ {'target': 'azul', 'message': 'Help:'}, {'target': 'azul', 'message': '.aaa | function a'}, {'target': 'azul', 'message': '.b | function b'}, ]
async def test_tell_handler(): with patch('chitanda.modules.tell._fetch_tells') as fetch: with patch('chitanda.modules.tell._delete_tell') as delete: fetch.return_value = [ { 'time': '2019-01-01T12:34:56', 'sender': 'azul', 'message': 'hi', 'id': 1, }, { 'time': '2019-01-02T12:34:56', 'sender': 'azul', 'message': 'hi again', 'id': 2, }, ] responses = [ r async for r in tell_handler( Message(None, None, None, 'newuser', None, False)) ] assert responses == [ 'newuser: On Jan 01, 12:34:56, azul said: hi', 'newuser: On Jan 02, 12:34:56, azul said: hi again', ] assert delete.call_args_list == [call(1), call(2)]
async def test_help_discord(applicable_listener, monkeypatch): monkeypatch.setattr( 'chitanda.modules.help.config', {'trigger_character': '.'} ) applicable_listener.return_value = True bot = Mock(commands={'aaa': Mock(call=a), 'b': Mock(call=b)}) response = [ r async for r in call( Message( bot=bot, listener=Mock(spec=DiscordListener), target='azul', author='azul', contents='', private=False, ) ) ][0] assert response['message'].title == 'Help!' assert response['message'].fields[0].name == '.aaa' assert response['message'].fields[0].value == 'function a' assert response['message'].fields[1].name == '.b' assert response['message'].fields[1].value == 'function b'
async def test_call_error(monkeypatch): monkeypatch.setattr( 'chitanda.modules.wolframalpha.config', { 'user_agent': 'chitanda', 'wolframalpha': { 'appid': 'abc' } }, ) monkeypatch.setattr( 'chitanda.modules.wolframalpha.requests', Mock( get=Mock(side_effect=RequestException), RequestException=RequestException, ), ) with pytest.raises(BotError): await call( Message( bot=None, listener=None, target=None, author=None, contents='hows the weather', private=False, ))
async def test_call(monkeypatch): monkeypatch.setattr( 'chitanda.modules.wolframalpha.config', { 'user_agent': 'chitanda', 'wolframalpha': { 'appid': 'abc' } }, ) monkeypatch.setattr( 'chitanda.modules.wolframalpha.requests', Mock( get=Mock(return_value=(Mock(text='its hot'))), RequestException=Exception, ), ) assert 'its hot' == await call( Message( bot=None, listener=None, target=None, author=None, contents='hows the weather', private=False, ))
async def test_aliases_discord(monkeypatch): monkeypatch.setattr( "chitanda.modules.aliases.config", { "trigger_character": ".", "aliases": { "global": { "a": "apples", "b": "bananas" } }, }, ) response = [ r async for r in call( Message( bot=None, listener=Mock(spec=DiscordListener), target=None, author="azul", contents="", private=False, )) ][0] assert response["message"].title == "Aliases" assert response["message"].fields[0].name == ".a" assert response["message"].fields[0].value == ".apples" assert response["message"].fields[1].name == ".b" assert response["message"].fields[1].value == ".bananas"
def test_parse_command_multi_word(monkeypatch): monkeypatch.setattr("chitanda.util.config", TEST_PARSE_CONFIG) cmd = Mock(__name__="multi_word", call=Mock(return_value=123)) bot = Mock(commands={"multi word": cmd}) message = Message(bot, "TestListener", 2, 3, ".multi word command", 5) assert 123 == message.call_command() assert cmd.call.call_args[0][0].contents == "command"
def test_parse_command_multi_word(monkeypatch): monkeypatch.setattr('chitanda.util.config', TEST_PARSE_CONFIG) cmd = Mock(__name__='multi_word', call=Mock(return_value=123)) bot = Mock(commands={'multi word': cmd}) message = Message(bot, 'TestListener', 2, 3, '.multi word command', 5) assert 123 == message.call_command() assert cmd.call.call_args[0][0].contents == 'command'
def test_parse_command_not_enabled(monkeypatch): monkeypatch.setattr('chitanda.util.config', TEST_PARSE_CONFIG) cmd = Mock(__name__='ramwolf', call=Mock(return_value=123)) bot = Mock(commands={'ramwolf': cmd}) message = Message(bot, 'AppleListener', 2, 3, '.ramwolf', 5) with pytest.raises(NoCommandFound): message.call_command()
async def test_auth_only_decorator_generator(): async def func(*args, **kwargs): for n in [1, 2, 3]: yield n listener = Mock(is_authed=AsyncMock(return_value=True)) assert [1, 2, 3] == [ n async for n in auth_only(func)(Message(None, listener, 2, "azul", 4, 5)) ]
async def test_say(): assert 'message' == await call( Message( bot=None, listener=None, target=None, author=None, contents='message', private=False, ))
async def test_auth_only_decorator_generator(): async def func(*args, **kwargs): for n in [1, 2, 3]: yield n listener = Mock() listener.is_authed.side_effect = coroutine(lambda *args, **kwargs: True) assert [1, 2, 3] == [ n async for n in auth_only(func)(Message(None, listener, 2, 'azul', 4, 5)) ]
async def test_choose_nothing(): with pytest.raises(BotError): await call( Message( bot=None, listener=None, target=None, author=None, contents='abc', private=False, ))
async def test_choose_string_space(): response = await call( Message( bot=None, listener=None, target=None, author=None, contents='a b c', private=False, )) assert isinstance(response, str) and response in {'a', 'b', 'c'}
async def test_choose_integer(): response = await call( Message( bot=None, listener=None, target=None, author=None, contents='1 - 4', private=False, )) assert isinstance(response, int) and response >= 1 and response <= 4
async def on_private_message(self, target, by, message): if by != self.nickname: message = Message( bot=self.bot, listener=self, target=by, author=by, contents=message, private=True, ) await self.bot.handle_message(message)
async def test_handle_message_bot_error(monkeypatch): monkeypatch.setattr('chitanda.bot.config', {'webserver': {'enable': True}}) listener = Mock() listener.message.return_value = Future() listener.message.return_value.set_result(123) chitanda = Chitanda() with patch.object(chitanda, 'message_handlers') as msg_handlers: msg_handlers.__iter__.side_effect = BotError('test error') message = Message(chitanda, listener, 2, 'azul', 4, 5) await chitanda.handle_message(message) listener.message.assert_called_with(2, f'Error: test error')
async def test_choose_string_comma(): response = await call( Message( bot=None, listener=None, target=None, author=None, contents="a, b, c", private=False, ) ) assert isinstance(response, str) and response in {"a", "b", "c"}
async def test_fetch_random_quote_nonexistent(test_db): assert ["This channel has no quotes saved."] == [ r async for r in fetch.call( Message( bot=None, listener="DiscordListener", target="#chan", author="azul", contents="", private=False, )) ]
async def test_fetch_quotes_overfetch(test_db): with pytest.raises(BotError): async for r in fetch.call( Message( bot=None, listener="DiscordListener", target="#chan", author="azul", contents="1 2 3 4 5", private=False, )): pass
async def test_reload(monkeypatch): monkeypatch.setattr("chitanda.modules.reload.config", Mock()) monkeypatch.setattr("chitanda.modules.reload.load_commands", Mock()) assert "Commands reloaded." == await call( Message( bot=None, listener=Mock(is_admin=AsyncMock(return_value=True)), target=None, author=None, contents="", private=False, ))
async def test_fetch_quotes_overfetch(test_db): with pytest.raises(BotError): async for r in fetch.call( Message( bot=None, listener='DiscordListener', target='#chan', author='azul', contents='1 2 3 4 5', private=False, )): pass
async def test_fetch_random_quote_nonexistent(test_db): assert ['This channel has no quotes saved.'] == [ r async for r in fetch.call( Message( bot=None, listener='DiscordListener', target='#chan', author='azul', contents='', private=False, )) ]
async def test_handle_message_bot_error(monkeypatch): monkeypatch.setattr("chitanda.bot.config", {"webserver": {"enable": True}}) listener = Mock() listener.message.return_value = Future() listener.message.return_value.set_result(123) chitanda = Chitanda() with patch.object(chitanda, "message_handlers") as msg_handlers: msg_handlers.__iter__.side_effect = BotError("test error") message = Message(chitanda, listener, 2, "azul", 4, 5) await chitanda.handle_message(message) listener.message.assert_called_with(2, "Error: test error")
async def on_message(self, message): if not message.author.bot: message = Message( bot=self.bot, listener=self, target=message.channel.id, author=message.author.id, contents=message.content, private=isinstance(message.channel, discord.DMChannel), raw=message, ) await self.bot.handle_message(message)