This commit is contained in:
j3d1 2026-08-24 15:57:17 +02:00
parent 8d96bc97c4
commit ed04d98bf1
54 changed files with 661 additions and 1214 deletions

View file

@ -85,20 +85,8 @@ class FriendApiTestCase(UserTestMixin, ToolshedTestCase):
self.assertEqual(self.f['local_user1'].friends.count(), 1)
# what ~should~ happen:
# 1. user x@A sends a friend request to user y@B
# 1.1. x@A's client sends a POST request to A/api/friendrequests/ with body {from: x@A, to: y@B}
# 1.2. A's backend creates a FriendRequestOutgoing object, containing x@A's identity and y@B's name
# 1.3. x@A's client sends a POST request to B/api/friendrequests/ with body
# {from: x@A, to: y@B, public_key: x@A's public key}
# 1.4. B's backend creates a FriendRequestIncoming object, containing y@B's and x@A's identities
# 2. user y@B accepts the friend request
# 2.1. y@B's client sends a POST request to A/api/friendsrequests/ with body
# {from: x@A, to: y@B, public_key: y@B's public key}
# 2.2. A's backend matches the data to the FriendRequestOutgoing object, deletes both and creates a Friend object,
# containing x@A's and y@B's identities
# 2.3. y@B's client sends a POST request to B/api/friends/ containing the id of the FriendRequestIncoming object
# 2.4. B's backend creates a Friend object, using the identities from the FriendRequestIncoming object
# Friend request/accept protocol walkthrough. See
# docs/implementation.md#friend-request-and-accept-protocol-flow.
class FriendRequestListTestCase(UserTestMixin, ToolshedTestCase):

View file

@ -388,9 +388,8 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
self.assertEqual(InventoryItem.objects.filter(id=item_id).count(), 0)
def test_remote_member_without_local_account_can_edit(self):
# A remote member (no ToolshedUser row at all on this backend, only a KnownIdentity -
# see docs/design-in-progress/groups-mvp.md) must still be able to act on group-owned
# items here; it must not be treated as unauthorized just because .user.exists() is False.
# A remote member (KnownIdentity, no ToolshedUser row) must still act on group-owned
# items - not unauthorized just because .user.exists() is False.
self.f['group1'].members.add(self.f['ext_user1'].public_identity)
item_id = self.create_group_item().json()['id']
reply = client.get('/api/inventory_items/{}/'.format(item_id), self.f['ext_user1'])
@ -426,8 +425,8 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
self.assertEqual(len(reply.json()), 0)
def test_create_group_owned_item_with_full_fields(self):
# Parity with InventoryApiTestCase.test_post_new_item - tags/properties/category must
# attach to a group-owned item exactly the same way they do for a personal one.
# Parity with InventoryApiTestCase.test_post_new_item: tags/properties/category attach
# to a group-owned item the same way as a personal one.
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
'availability_policy': 'rent',
'category': 'cat2',
@ -450,8 +449,7 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
self.assertEqual([p.value for p in item.itemproperty_set.all()], ['value1', 'value2'])
def test_create_group_owned_item_empty_fails(self):
# Parity with InventoryApiTestCase.test_post_new_item_empty - clean()'s name-or-files
# validation must still apply to group-owned items.
# Parity with InventoryApiTestCase.test_post_new_item_empty: clean()'s name-or-files validation still applies.
reply = client.post('/api/inventory_items/', self.f['local_user1'], {
'availability_policy': 'private', 'owned_quantity': 1, 'owner_group': self.f['group1'].id,
})
@ -471,9 +469,8 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
self.assertEqual(len(reply.json()), 0)
def test_put_group_item(self):
# Parity with InventoryApiTestCase.test_put_item - full replace, by a different member
# than the one who created it, exercising the group_items_id -> _is_authorized branch
# in perform_update for a PUT (not just PATCH).
# Parity with InventoryApiTestCase.test_put_item, but as a PUT by a different member than
# the creator, to exercise the _is_authorized branch in perform_update for PUT too.
item_id = self.create_group_item().json()['id']
reply = client.put('/api/inventory_items/{}/'.format(item_id), self.f['local_user2'], {
'availability_policy': 'sell',
@ -539,9 +536,8 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
self.assertEqual([f for f in item.files.all()], [self.f['test_file3']])
def test_group_items_excluded_from_search(self):
# Group-owned items are only ever reachable via the group's own detail page for MVP
# (see docs/design-in-progress/groups-mvp.md) - search must not surface them, same as
# the main Inventory list already doesn't.
# Group-owned items are reachable only via the group's own detail page for MVP (see
# docs/design-in-progress/groups-mvp.md) - search must not surface them either.
self.create_group_item(name='searchable-drill')
InventoryItem.create_for_owner(owner=self.f['local_user1'], owned_quantity=1, name='searchable-personal')
reply = client.get('/api/search/?query=searchable', self.f['local_user1'])
@ -551,8 +547,8 @@ class GroupOwnedInventoryApiTestCase(UserTestMixin, GroupTestMixin, CategoryTest
class InventoryItemIdAllocationTestCase(UserTestMixin, ToolshedTestCase):
"""InventoryItem.id is sequential and gapless within each owner/owner_group's own items,
never reused, and allocated independently per scope - see OwnerItemSequence."""
"""InventoryItem.id is sequential, gapless, and never reused within each owner/owner_group's
own items, allocated independently per scope (see OwnerItemSequence)."""
def setUp(self):
super().setUp()

View file

@ -123,10 +123,7 @@ class DeleteAccountTestCase(_DeleteTestDataMixin, ToolshedTestCase):
class ImportInventoryPropertiesTestCase(UserTestMixin, CategoryTestMixin, TagTestMixin, PropertyTestMixin,
ToolshedTestCase):
"""Properties must round-trip through export/import even when their value contains a
comma or an '=' sign - characters that a naive "handle=value, handle2=value2" encoding of
the 'properties' CSV cell would misinterpret as a field/entry separator.
"""
"""Properties must round-trip through export/import even when their value contains a comma or '=' sign, which a naive "handle=value, handle2=value2" encoding would otherwise misinterpret as a separator."""
def setUp(self):
super().setUp()
@ -222,10 +219,7 @@ class ImportInventoryPropertiesTestCase(UserTestMixin, CategoryTestMixin, TagTes
class ExportImportApiRoundTripTestCase(UserTestMixin, CategoryTestMixin, TagTestMixin, PropertyTestMixin,
ToolshedTestCase):
"""End-to-end coverage of the /api/export/ + /api/import/ endpoints (as actually used by
clients), rather than calling the internal helper functions directly - this is what a real
export/import round trip between two accounts looks like.
"""
"""End-to-end coverage of the /api/export/ + /api/import/ endpoints (as actually used by clients), rather than calling the internal helper functions directly - this is what a real export/import round trip between two accounts looks like."""
def setUp(self):
super().setUp()