Skip to content

Commit 083dcbb

Browse files
committed
- Finish the game endpoints
- Fill out tests
1 parent f73c46d commit 083dcbb

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

kirovy/serializers/cnc_game_serializers.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class CncGameSerializer(KirovySerializer):
4747
is_visible = serializers.BooleanField(allow_null=False, default=True)
4848
allow_public_uploads = serializers.BooleanField(allow_null=False, default=False)
4949
compatible_with_parent_maps = serializers.BooleanField(allow_null=False, default=False)
50-
is_mod = serializers.BooleanField(allow_null=False, default=False)
50+
is_mod = serializers.BooleanField(read_only=True, allow_null=False, default=False)
5151
allowed_extension_ids = serializers.PrimaryKeyRelatedField(
5252
source="allowed_extensions",
5353
pk_field=serializers.UUIDField(),
@@ -57,12 +57,12 @@ class CncGameSerializer(KirovySerializer):
5757

5858
parent_game_id = serializers.PrimaryKeyRelatedField(
5959
source="parent_game",
60-
queryset=cnc_game.CncGame.objects.filter(is_visible=True),
6160
pk_field=serializers.UUIDField(),
6261
many=False,
6362
allow_null=True,
6463
allow_empty=False,
6564
default=None,
65+
read_only=True, # parent_id affects file path generation so we can't change it via the API.
6666
)
6767

6868
class Meta:
@@ -75,3 +75,17 @@ def create(self, validated_data: t.DictStrAny) -> cnc_game.CncGame:
7575
instance = cnc_game.CncGame(**validated_data)
7676
instance.save()
7777
return instance
78+
79+
def update(self, instance: cnc_game.CncGame, validated_data: t.DictStrAny) -> cnc_game.CncGame:
80+
instance.full_name = validated_data.get("full_name", instance.full_name)
81+
instance.is_visible = validated_data.get("is_visible", instance.is_visible)
82+
instance.is_mod = validated_data.get("is_mod", instance.is_mod)
83+
instance.allow_public_uploads = validated_data.get("allow_public_uploads", instance.allow_public_uploads)
84+
instance.compatible_with_parent_maps = validated_data.get(
85+
"compatible_with_parent_maps", instance.compatible_with_parent_maps
86+
)
87+
instance.save(
88+
update_fields=["full_name", "is_visible", "is_mod", "allow_public_uploads", "compatible_with_parent_maps"]
89+
)
90+
instance.refresh_from_db()
91+
return instance

tests/test_views/test_game_views.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,59 @@ def test_game__hidden_games_visible_to_moderators(client_moderator, create_cnc_g
5858
assert response.status_code == status.HTTP_200_OK
5959

6060
assert str(invisible.id) in [r["id"] for r in response.data["results"]]
61+
62+
63+
def test_game__cannot_be_deleted(client_god, create_cnc_game):
64+
"""C&C games don't change much these days, so there's no real reason to expose deletions to the API.
65+
66+
If you are a future person and are adding more capabilities to the game endpoints, you can just alter this test
67+
to use the ``client_user`` fixture to test that user's can't delete games.
68+
"""
69+
my_game = create_cnc_game()
70+
71+
response = client_god.delete(f"/games/{my_game.id}/", data_type=ui_objects.ResultResponseData)
72+
73+
assert response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
74+
75+
76+
def test_game__cannot_be_edited_by_non_admins(client_moderator, create_cnc_game):
77+
"""C&C games don't change much so we'll only allow admins to edit them via the API.
78+
79+
Maybe in the future we can allow mod authors to edit their own mod entries."""
80+
my_game = create_cnc_game()
81+
82+
response = client_moderator.post(f"/games/{my_game.id}/", data_type=ui_objects.ResultResponseData)
83+
84+
assert response.status_code == status.HTTP_403_FORBIDDEN
85+
86+
87+
def test_game__admins_can_edit(client_admin, create_cnc_game):
88+
"""Admins should be able to edit a few non-structural things for games via the API."""
89+
my_game = create_cnc_game()
90+
new_full_name = f"{my_game.full_name} (Steam version)"
91+
new_visibility = not my_game.is_visible
92+
new_allow_public_uploads = not my_game.allow_public_uploads
93+
new_compatible_with_parent_maps = not my_game.compatible_with_parent_maps
94+
original_is_mod = my_game.is_mod
95+
original_slug = my_game.slug
96+
97+
data = {
98+
"full_name": new_full_name,
99+
"is_visible": new_visibility,
100+
"allow_public_uploads": new_allow_public_uploads,
101+
"compatible_with_parent_maps": new_compatible_with_parent_maps,
102+
"is_mod": not original_is_mod, # should not change, not editable via API.
103+
"slug": "wontwork", # should not change, not editable via API.
104+
}
105+
106+
response = client_admin.patch(f"/games/{my_game.id}/", data=data, data_type=ui_objects.ResultResponseData)
107+
108+
assert response.status_code == status.HTTP_200_OK
109+
my_game.refresh_from_db()
110+
111+
assert my_game.full_name == new_full_name
112+
assert my_game.is_visible == new_visibility
113+
assert my_game.allow_public_uploads == new_allow_public_uploads
114+
assert my_game.compatible_with_parent_maps == new_compatible_with_parent_maps
115+
assert my_game.is_mod == original_is_mod, "should not be changeable via the API."
116+
assert my_game.slug == original_slug, "should not be changeable via the API."

0 commit comments

Comments
 (0)