diff --git a/CHANGELOG.md b/CHANGELOG.md index 41bde9c50..41dc92cb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,16 @@ - Feature: Add `ON_DEMAND_HANDLER.set_dt(key, category, dt)` and `.set_stage(key, category, stage)` to allow manual tweaking of task timings, - for example for a spell speeding a plant's growth. (Griatch) -- Fix: Resolve a bug when loading on-demand-handler data from database. + for example for a spell speeding a plant's growth (Griatch) +- Feature: Add `use_assertequal` kwarg to the `EvenniaCommandTestMixin` testing + class; this uses django's `assertEqual` over the default more lenient checker, + which can be useful for testing table whitespace (Griatch) +- [Fix][pull3420]: Refactor Clothing contrib's inventory command align with + Evennia core's version (michaelfaith84, Griatch) +- Fix: Resolve a bug when loading on-demand-handler data from database (Griatch) +- Doc fixes (iLPdev, Griatch) + +[pull3420]: https://github.com/evennia/evennia/pull/3420 ## Evennia 3.2.0 diff --git a/evennia/contrib/game_systems/clothing/clothing.py b/evennia/contrib/game_systems/clothing/clothing.py index d4ba95bf9..6c53eeac6 100644 --- a/evennia/contrib/game_systems/clothing/clothing.py +++ b/evennia/contrib/game_systems/clothing/clothing.py @@ -75,10 +75,10 @@ with which to test the system: from collections import defaultdict from django.conf import settings - from evennia import DefaultCharacter, DefaultObject, default_cmds from evennia.commands.default.muxcommand import MuxCommand -from evennia.utils import at_search_result, evtable, inherits_from, iter_to_str, int2str +from evennia.utils import at_search_result, crop, evtable, inherits_from, int2str, iter_to_str +from evennia.utils.ansi import raw as raw_ansi # Options start here. # Maximum character length of 'wear style' strings, or None for unlimited. @@ -468,7 +468,8 @@ class CmdWear(MuxCommand): return elif len(self.rhs) > WEARSTYLE_MAXLENGTH: self.caller.msg( - f"Please keep your wear style message to less than {WEARSTYLE_MAXLENGTH} characters." + "Please keep your wear style message to less than" + f" {WEARSTYLE_MAXLENGTH} characters." ) return else: @@ -652,39 +653,38 @@ class CmdInventory(MuxCommand): message_list = [] + # all our items items = self.caller.contents - carry_table = evtable.EvTable(border="header") - wear_table = evtable.EvTable(border="header") - + # carried items carried = [obj for obj in items if not obj.db.worn] + carry_table = self.styled_table(border="header") - names_and_descs = [(obj.get_display_name(self.caller), obj.get_display_desc(self.caller)) - for obj in set(carried)] - carried_sums = {tup: names_and_descs.count(tup) for tup in set(names_and_descs)} - - worn = [obj for obj in items if obj.db.worn] - - message_list.append("|wYou are carrying:|n") - for (name, desc), count in carried_sums.items(): + for item in carried: + singular, _ = item.get_numbered_name(1, self.caller) carry_table.add_row( - f"{int2str(count)} {name}", desc + f"{singular}|n", + "{}|n".format(crop(raw_ansi(item.db.desc or ""), width=50) or ""), ) + message_list.extend( + ["|wYou are carrying:|n", str(carry_table) if carry_table.nrows > 0 else " Nothing."] + ) - if carry_table.nrows == 0: - carry_table.add_row("Nothing.", "") - message_list.append(str(carry_table)) + # worn items + worn = [obj for obj in items if obj.db.worn] + wear_table = self.styled_table(border="header") - message_list.append("|wYou are wearing:|n") for item in worn: - item_name = item.get_display_name(self.caller) - if item.db.covered_by: - item_name += " (hidden)" - wear_table.add_row(item_name, item.get_display_desc(self.caller)) - if wear_table.nrows == 0: - wear_table.add_row("Nothing.", "") - message_list.append(str(wear_table)) + singular, _ = item.get_numbered_name(1, self.caller) + wear_table.add_row( + f"{singular}|n", + "{}|n".format(crop(raw_ansi(item.db.desc or ""), width=50) or ""), + ) + message_list.extend( + ["You are wearing:|n", str(wear_table) if wear_table.nrows > 0 else " Nothing."] + ) + # return the composite message self.caller.msg("\n".join(message_list)) diff --git a/evennia/contrib/game_systems/clothing/tests.py b/evennia/contrib/game_systems/clothing/tests.py index eae18cb32..637f703d6 100644 --- a/evennia/contrib/game_systems/clothing/tests.py +++ b/evennia/contrib/game_systems/clothing/tests.py @@ -25,7 +25,7 @@ class TestClothingCmd(BaseEvenniaCommandTest): self.test_scarf.db.clothing_type = "accessory" def test_clothingcommands(self): - # Test inventory command. + # Test inventory command with no items self.call( clothing.CmdInventory(), "", @@ -33,9 +33,19 @@ class TestClothingCmd(BaseEvenniaCommandTest): caller=self.wearer, ) - # Test wear command + # add the hat and scarf to the wearer self.test_scarf.location = self.wearer self.test_hat.location = self.wearer + + self.call( + clothing.CmdInventory(), + "", + "You are carrying:\n a test scarf \n a test hat \nYou are wearing:\n Nothing.", + caller=self.wearer, + use_assertequal=True, + ) + + # Test wear command self.call(clothing.CmdWear(), "", "Usage: wear [=] [wear style]", caller=self.wearer) self.call(clothing.CmdWear(), "hat", "You put on test hat.", caller=self.wearer) self.call( @@ -57,6 +67,15 @@ class TestClothingCmd(BaseEvenniaCommandTest): "You cover test hat with test scarf.", caller=self.wearer, ) + + self.call( + clothing.CmdInventory(), + "", + "You are carrying:\n Nothing.\nYou are wearing:\n a test scarf \n a test hat ", + caller=self.wearer, + use_assertequal=True, + ) + # Test remove command. self.call(clothing.CmdRemove(), "", "Could not find ''.", caller=self.wearer) self.call( diff --git a/evennia/utils/test_resources.py b/evennia/utils/test_resources.py index 9dc8c6b7f..44802a832 100644 --- a/evennia/utils/test_resources.py +++ b/evennia/utils/test_resources.py @@ -26,27 +26,21 @@ import re import sys import types +import evennia from django.conf import settings from django.test import TestCase, override_settings -from mock import MagicMock, Mock, patch -from twisted.internet.defer import Deferred - -import evennia from evennia import settings_default from evennia.accounts.accounts import DefaultAccount from evennia.commands.command import InterruptCommand from evennia.commands.default.muxcommand import MuxCommand -from evennia.objects.objects import ( - DefaultCharacter, - DefaultExit, - DefaultObject, - DefaultRoom, -) +from evennia.objects.objects import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom from evennia.scripts.scripts import DefaultScript from evennia.server.serversession import ServerSession from evennia.utils import ansi, create from evennia.utils.idmapper.models import flush_cache from evennia.utils.utils import all_from_module, to_str +from mock import MagicMock, Mock, patch +from twisted.internet.defer import Deferred _RE_STRIP_EVMENU = re.compile(r"^\+|-+\+|\+-+|--+|\|(?:\s|$)", re.MULTILINE) @@ -336,6 +330,7 @@ class EvenniaCommandTestMixin: obj=None, inputs=None, raw_string=None, + use_assertequal=False, ): """ Test a command by assigning all the needed properties to a cmdobj and @@ -394,6 +389,9 @@ class EvenniaCommandTestMixin: a combination of your `key/cmdname` and `input_args`. This allows direct control of what this is, for example for testing edge cases or malformed inputs. + use_assertequal (bool, optional): If `True`, the error message will use + a regular assertEqual. This will show show whitepace differences easier, but + doesn't allow for only matching against the start of the returned message. Returns: str or dict: The message sent to `receiver`, or a dict of @@ -529,6 +527,11 @@ class EvenniaCommandTestMixin: ).strip() # this is the actual test + + if use_assertequal: + # regular django assert shows whitespace differences better + self.assertEqual(returned_msg, expected_msg) + if expected_msg == "" and returned_msg or not returned_msg.startswith(expected_msg): # failed the test raise AssertionError(