diff --git a/games/models.py b/games/models.py index 86cd516..3babdd3 100644 --- a/games/models.py +++ b/games/models.py @@ -12,6 +12,7 @@ from django.template.defaultfilters import floatformat, pluralize, slugify from django.utils import timezone from common.time import format_duration +from common.utils import label_with_details logger = logging.getLogger("games") @@ -67,7 +68,7 @@ class Game(models.Model): @property def search_label(self) -> str: - return f"{self.sort_name} ({self.platform}, {self.year_released})" + return label_with_details(self.name, self.platform, self.year_released) def finished(self): return ( @@ -234,16 +235,12 @@ class Purchase(models.Model): @property def full_name(self): - additional_info = [ - str(item) - for item in [ - f"{self.num_purchases} game{pluralize(self.num_purchases)}", - self.date_purchased, - self.standardized_price, - ] - if item - ] - return f"{self.standardized_name} ({', '.join(additional_info)})" + return label_with_details( + self.standardized_name, + f"{self.num_purchases} game{pluralize(self.num_purchases)}", + self.date_purchased, + self.standardized_price, + ) def is_game(self): return self.type == self.GAME diff --git a/tests/test_purchase_separate_orders.py b/tests/test_purchase_separate_orders.py index 1893edf..f8bc359 100644 --- a/tests/test_purchase_separate_orders.py +++ b/tests/test_purchase_separate_orders.py @@ -63,6 +63,21 @@ class AddPurchasePricingTest(TestCase): {self.game_a.id, self.game_b.id}, ) + def test_full_name_keeps_parenthesized_detail_shape(self): + bundle = Purchase.objects.create( + name="Humble Bundle", + date_purchased=date(2025, 1, 1), + price=30, + price_currency="USD", + ownership_type=Purchase.DIGITAL, + ) + bundle.games.set([self.game_a, self.game_b]) + bundle.refresh_from_db() + + full_name = bundle.full_name + self.assertTrue(full_name.startswith("Humble Bundle (2 games, ")) + self.assertTrue(full_name.endswith(")")) + class SplitPurchaseTest(TestCase): def setUp(self): diff --git a/tests/test_search_select.py b/tests/test_search_select.py index 36dcfe9..e143701 100644 --- a/tests/test_search_select.py +++ b/tests/test_search_select.py @@ -338,6 +338,26 @@ class SearchLabelTest(django.test.TestCase): def test_format(self): self.assertEqual(self.game.search_label, "Mario (Steam, 2020)") + def test_format_uses_name_not_sort_name(self): + game = Game.objects.create( + name="Tetris", sort_name="", platform=self.platform, year_released=1984 + ) + self.assertEqual(game.search_label, "Tetris (Steam, 1984)") + + def test_format_omits_missing_year(self): + game = Game.objects.create(name="Tetris", platform=self.platform) + self.assertEqual(game.search_label, "Tetris (Steam)") + + def test_format_uses_sentinel_platform_when_unset(self): + # Game.save() substitutes the "Unspecified" sentinel platform, so the + # platform part is never a literal "None"; only year_released can drop out. + game = Game.objects.create(name="Tetris", year_released=1984) + self.assertEqual(game.search_label, "Tetris (Unspecified, 1984)") + + def test_format_with_sentinel_platform_and_no_year(self): + game = Game.objects.create(name="Tetris") + self.assertEqual(game.search_label, "Tetris (Unspecified)") + def test_choice_fields_use_search_label(self): from games.forms import MultipleGameChoiceField, SingleGameChoiceField