258 lines
11 KiB
Python
258 lines
11 KiB
Python
"""Test IdleRPG character operations.
|
|
|
|
SPDX-FileCopyrightText: © 2024 Brian S. Stephan <bss@incorporeal.org>
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
import logging
|
|
import re
|
|
import unittest.mock as mock
|
|
|
|
from django.test import TestCase
|
|
from django.utils import timezone
|
|
|
|
from ircbot.models import IrcChannel, IrcServer
|
|
from idlerpg.ircplugin import IdleRPG
|
|
from idlerpg.models import Character, Game
|
|
|
|
|
|
class IrcPluginTest(TestCase):
|
|
"""Test the IRC integration."""
|
|
|
|
fixtures = ['tests/fixtures/simple_character.json']
|
|
|
|
def setUp(self):
|
|
"""Create common objects."""
|
|
self.mock_bot = mock.MagicMock()
|
|
self.mock_connection = mock.MagicMock()
|
|
|
|
self.mock_connection.get_nickname.return_value = 'test_bot'
|
|
self.mock_connection.server_config = IrcServer.objects.get(pk=1)
|
|
|
|
self.plugin = IdleRPG(self.mock_bot, self.mock_connection, mock.MagicMock())
|
|
self.game = Game.objects.get(pk=1)
|
|
|
|
def test_kick_penalty(self):
|
|
"""Test that if a character is kicked from the game channel, they get penalized."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_kick_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
# make a character so as to not disturb other tests
|
|
test_char = Character.objects.register('testkickpen', self.game, 'test',
|
|
'bss!bss@test_kick_penalty', 'tester')
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
with mock.patch('idlerpg.models.Character.log_out') as mock_log_out:
|
|
self.plugin.handle_kick_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_called_with(250, "getting kicked from the game channel")
|
|
mock_log_out.assert_called()
|
|
test_char = Character.objects.get(name='testkickpen')
|
|
assert test_char.time_penalized_kicked == 5
|
|
|
|
test_char.delete()
|
|
|
|
def test_generic_penalty_no_penalty_for_unknown(self):
|
|
"""Test that a kick from an unknown hostmask is ignored."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_kick_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
with mock.patch('idlerpg.models.Character.log_out') as mock_log_out:
|
|
self.plugin.handle_kick_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_not_called()
|
|
mock_log_out.assert_not_called()
|
|
|
|
def test_nick_penalty(self):
|
|
"""Test that if a user changes their nick, they get penalized."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_nick_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
# make a character so as to not disturb other tests
|
|
test_char = Character.objects.register('testnickpen', self.game, 'test',
|
|
'bss!bss@test_nick_penalty', 'tester')
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
with mock.patch('idlerpg.models.Character.log_out') as mock_log_out:
|
|
self.plugin.handle_nick_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_called_with(30, "changing their nick")
|
|
mock_log_out.assert_called()
|
|
test_char = Character.objects.get(name='testnickpen')
|
|
assert test_char.time_penalized_nick_change == 5
|
|
|
|
test_char.delete()
|
|
|
|
def test_part_penalty(self):
|
|
"""Test that if a character parts from the game channel, they get penalized."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_part_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
# make a character so as to not disturb other tests
|
|
test_char = Character.objects.register('testpartpen', self.game, 'test',
|
|
'bss!bss@test_part_penalty', 'tester')
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
with mock.patch('idlerpg.models.Character.log_out') as mock_log_out:
|
|
self.plugin.handle_part_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_called_with(200, "parting the game channel")
|
|
mock_log_out.assert_called()
|
|
test_char = Character.objects.get(name='testpartpen')
|
|
assert test_char.time_penalized_part == 5
|
|
|
|
test_char.delete()
|
|
|
|
def test_pubmsg_penalty(self):
|
|
"""Test that if a character speaks in the game channel, they get penalized."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.arguments = ['this is a test message']
|
|
mock_event.source = 'bss!bss@test_pubmsg_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
# make a character so as to not disturb other tests
|
|
test_char = Character.objects.register('testpubmsgpen', self.game, 'test',
|
|
'bss!bss@test_pubmsg_penalty', 'tester')
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
self.plugin.handle_message_penalty(self.mock_connection, mock_event)
|
|
|
|
# 22 is the len of the message
|
|
mock_penalize.assert_called_with(22, "sending a privmsg to the game channel")
|
|
test_char = Character.objects.get(name='testpubmsgpen')
|
|
assert test_char.time_penalized_privmsg == 5
|
|
|
|
test_char.delete()
|
|
|
|
def test_pubmsg_no_penalty_for_unknown(self):
|
|
"""Test that a speakerwith an unknown hostmask is ignored."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.arguments = ['this is a test message']
|
|
mock_event.source = 'bss!bss@some_user'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
self.plugin.handle_message_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_not_called()
|
|
|
|
def test_join(self):
|
|
"""Test that joiners update the seen hostmasks."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.arguments = ['this is a test message']
|
|
mock_event.source = 'test!test@test_join'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
assert 'test!test@test_join' not in self.plugin.seen_hostmasks
|
|
self.plugin.handle_join(self.mock_connection, mock_event)
|
|
assert 'test!test@test_join' in self.plugin.seen_hostmasks
|
|
|
|
def test_quit_penalty(self):
|
|
"""Test that if a character quits from the game channel, they get penalized."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_quit_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
# make a character so as to not disturb other tests
|
|
test_char = Character.objects.register('testquitpen', self.game, 'test',
|
|
'bss!bss@test_quit_penalty', 'tester')
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
with mock.patch('idlerpg.models.Character.log_out') as mock_log_out:
|
|
self.plugin.handle_quit_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_called_with(20, "quitting IRC")
|
|
mock_log_out.assert_called()
|
|
test_char = Character.objects.get(name='testquitpen')
|
|
assert test_char.time_penalized_quit == 5
|
|
|
|
test_char.delete()
|
|
|
|
def test_quit_penalty_even_if_logged_out(self):
|
|
"""Test that the penalty applies even if the character is already logged out."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_quit_penalty'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
# make a character so as to not disturb other tests
|
|
test_char = Character.objects.register('testquitpen', self.game, 'test',
|
|
'bss!bss@test_quit_penalty', 'tester')
|
|
with mock.patch('idlerpg.models.Character.penalize', return_value=5) as mock_penalize:
|
|
with mock.patch('idlerpg.models.Character.log_out', side_effect=ValueError) as mock_log_out:
|
|
self.plugin.handle_quit_penalty(self.mock_connection, mock_event)
|
|
|
|
mock_penalize.assert_called_with(20, "quitting IRC")
|
|
mock_log_out.assert_called()
|
|
test_char = Character.objects.get(name='testquitpen')
|
|
assert test_char.time_penalized_quit == 5
|
|
|
|
test_char.delete()
|
|
|
|
def test_login_character_not_found(self):
|
|
"""Test the LOGIN command sent to the bot."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_login'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
match = re.match(IdleRPG.LOGIN_COMMAND_PATTERN, 'LOGIN nope bss')
|
|
self.plugin.handle_login(self.mock_connection, mock_event, match)
|
|
|
|
self.mock_bot.reply.assert_called_once_with(
|
|
mock_event,
|
|
"The requested character does not exist, or has been disabled, or your password does not match."
|
|
)
|
|
|
|
def test_login_bad_password(self):
|
|
"""Test the LOGIN command sent to the bot."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_login'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
match = re.match(IdleRPG.LOGIN_COMMAND_PATTERN, 'LOGIN bss nope')
|
|
self.plugin.handle_login(self.mock_connection, mock_event, match)
|
|
|
|
self.mock_bot.reply.assert_called_once_with(
|
|
mock_event,
|
|
"The requested character does not exist, or has been disabled, or your password does not match."
|
|
)
|
|
|
|
def test_login_not_seen(self):
|
|
"""Test the LOGIN command sent to the bot."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_login'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
match = re.match(IdleRPG.LOGIN_COMMAND_PATTERN, 'LOGIN bss bss')
|
|
self.plugin.handle_login(self.mock_connection, mock_event, match)
|
|
|
|
self.mock_bot.reply.assert_called_once_with(mock_event, "Please join #test before logging in.")
|
|
|
|
def test_login_not_logged_off(self):
|
|
"""Test the LOGIN command sent to the bot."""
|
|
mock_event = mock.MagicMock()
|
|
mock_event.source = 'bss!bss@test_login'
|
|
mock_event.target = '#test'
|
|
mock_event.recursing = False
|
|
|
|
self.plugin.seen_hostmasks.add('bss!bss@test_login')
|
|
match = re.match(IdleRPG.LOGIN_COMMAND_PATTERN, 'LOGIN bss bss')
|
|
self.plugin.handle_login(self.mock_connection, mock_event, match)
|
|
|
|
self.mock_bot.reply.assert_called_once_with(
|
|
mock_event,
|
|
"Cannot log in bss, either they already are, or they are in a state that cannot be modified."
|
|
)
|
|
|
|
self.plugin.seen_hostmasks.remove('bss!bss@test_login')
|