Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test coverage for WebSocket messages #351

Merged
merged 5 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
"args": ["runserver"],
"django": true,
"justMyCode": true
}
},
]
}
3 changes: 2 additions & 1 deletion backend/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"editor.tabSize": 4,
"editor.insertSpaces": true
"editor.insertSpaces": true,
"python.testing.pytestEnabled": true,
}
3 changes: 3 additions & 0 deletions backend/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
DJANGO_SETTINGS_MODULE=rorapp.settings
python_files=*tests.py
3 changes: 2 additions & 1 deletion backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ daphne==4.0.0
dj-database-url==2.0.0
Django==4.2.3
django-cors-headers==3.13.0
django-debug-toolbar==4.1.0
djangorestframework==3.14.0
djangorestframework-simplejwt==5.2.2
psycopg2-binary==2.9.6
python-dotenv==0.21.0
pytest==7.4.0
pytest-django==4.7.0
12 changes: 10 additions & 2 deletions backend/rorapp/admin/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@
# Admin configuration for actions
@admin.register(Action)
class ActionAdmin(admin.ModelAdmin):
list_display = ("__str__", "game", "step", "faction", "type", "required", "completed")
list_filter = ("type", "required", "completed")
list_display = (
"__str__",
"game",
"step",
"faction",
"type",
"required",
"completed",
)
list_filter = ("required", "completed")
search_fields = ("step__phase__turn__game__id", "step__id", "faction__id", "type")

@admin.display(ordering="step__phase__turn__game__id")
Expand Down
20 changes: 19 additions & 1 deletion backend/rorapp/admin/senator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,22 @@
# Admin configuration for senators
@admin.register(Senator)
class SenatorAdmin(admin.ModelAdmin):
list_display = ("__str__", 'name', 'game', 'faction', 'death_step', 'code', 'generation', 'rank')
list_display = (
"__str__",
"game",
"faction",
"name",
"code",
"generation",
"death_step",
"rank",
)
search_fields = (
"game__id",
"faction__id",
"name",
"code",
"generation",
"death_step__id",
"rank",
)
8 changes: 3 additions & 5 deletions backend/rorapp/functions/faction_leader_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)
from rorapp.functions.mortality_phase_starter import setup_mortality_phase
from rorapp.functions.websocket_message_helper import (
send_websocket_messages,
create_websocket_message,
destroy_websocket_message,
)
Expand All @@ -30,7 +29,7 @@
)


def select_faction_leader(action_id, data) -> Response:
def select_faction_leader(action_id, data) -> (Response, dict):
"""
Select a faction leader.

Expand Down Expand Up @@ -58,7 +57,7 @@ def select_faction_leader(action_id, data) -> Response:
return set_faction_leader(senator.id)


def set_faction_leader(senator_id: int) -> Response:
def set_faction_leader(senator_id: int) -> (Response, dict):
senator = Senator.objects.get(id=senator_id)
game = Game.objects.get(id=senator.game.id)
faction = Faction.objects.get(id=senator.faction.id)
Expand Down Expand Up @@ -87,9 +86,8 @@ def set_faction_leader(senator_id: int) -> Response:
messages_to_send.extend(proceed_to_next_step_if_faction_phase(game.id, step))
messages_to_send.extend(proceed_to_next_step_if_forum_phase(game.id, step, faction))
messages_to_send.extend(delete_old_actions(game.id))
send_websocket_messages(game.id, messages_to_send)

return Response({"message": "Faction leader selected"}, status=200)
return Response({"message": "Faction leader selected"}, status=200), messages_to_send


def get_previous_title(faction) -> Optional[Title]:
Expand Down
8 changes: 4 additions & 4 deletions backend/rorapp/functions/mortality_phase_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from rorapp.functions.mortality_chit_helper import draw_mortality_chits
from rorapp.functions.rank_helper import rank_senators_and_factions
from rorapp.functions.websocket_message_helper import (
send_websocket_messages,
create_websocket_message,
destroy_websocket_message,
)
Expand All @@ -33,7 +32,9 @@
)


def face_mortality(action_id: int, chit_codes: List[int] | None = None) -> Response:
def face_mortality(
action_id: int, chit_codes: List[int] | None = None
) -> (Response, dict):
"""
Ready up for facing mortality.

Expand All @@ -60,8 +61,7 @@ def face_mortality(action_id: int, chit_codes: List[int] | None = None) -> Respo
if Action.objects.filter(step__id=action.step.id, completed=False).count() == 0:
messages_to_send.extend(resolve_mortality(game.id, chit_codes))

send_websocket_messages(game.id, messages_to_send)
return Response({"message": "Ready for mortality"}, status=200)
return Response({"message": "Ready for mortality"}, status=200), messages_to_send


def resolve_mortality(game_id: int, chit_codes: List[int] | None = None) -> dict:
Expand Down
21 changes: 14 additions & 7 deletions backend/rorapp/tests/mortality_phase_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ def kill_hrao(self, game_id: int) -> None:
game_id, "Temporary Rome Consul"
)[0]

latest_action_log = self.kill_senators(game_id, [highest_ranking_senator.id])[0]
action_logs, messages = self.kill_senators(game_id, [highest_ranking_senator.id])
self.assertEqual(len(messages), 18)
latest_action_log = action_logs[0]

self.assertIsNone(latest_action_log.data["heir_senator"])
self.assertEqual(
Expand All @@ -146,7 +148,9 @@ def kill_faction_leader(self, game_id: int) -> None:
self.assertEqual(faction_leader.name, "Aurelius")
faction_leader_title = Title.objects.get(senator=faction_leader)

latest_action_log = self.kill_senators(game_id, [faction_leader.id])[0]
action_logs, messages = self.kill_senators(game_id, [faction_leader.id])
self.assertEqual(len(messages), 11)
latest_action_log = action_logs[0]

heir_id = latest_action_log.data["heir_senator"]
heir = Senator.objects.get(id=heir_id)
Expand All @@ -170,7 +174,9 @@ def kill_regular_senator(self, game_id: int) -> None:
).count()
regular_senator = self.get_senators_with_title(game_id, None)[0]

latest_action_log = self.kill_senators(game_id, [regular_senator.id])[0]
action_logs, messages = self.kill_senators(game_id, [regular_senator.id])
self.assertEqual(len(messages), 8)
latest_action_log = action_logs[0]

self.assertIsNone(latest_action_log.data["heir_senator"])
self.assertIsNone(latest_action_log.data["major_office"])
Expand All @@ -185,17 +191,18 @@ def kill_two_senators(self, game_id: int) -> None:
).count()
two_regular_senators = self.get_senators_with_title(game_id, None)[0:2]
senator_ids = [senator.id for senator in two_regular_senators]
self.kill_senators(game_id, senator_ids)
latest_action_log, messages = self.kill_senators(game_id, senator_ids)
self.assertEqual(len(messages), 14)
post_death_living_senator_count = Senator.objects.filter(
game=game_id, death_step=None
).count()
self.assertEqual(living_senator_count - 2, post_death_living_senator_count)

def kill_senators(self, game_id: int, senator_ids: List[int]) -> List[ActionLog]:
def kill_senators(self, game_id: int, senator_ids: List[int]) -> (List[ActionLog], dict):
senators = Senator.objects.filter(id__in=senator_ids)
senator_codes = [senator.code for senator in senators]
self.assertEqual(len(senator_codes), len(senator_ids))
resolve_mortality(game_id, senator_codes)
messages = resolve_mortality(game_id, senator_codes)
latest_step = Step.objects.filter(phase__turn__game=game_id).order_by("-index")[
1
]
Expand All @@ -209,7 +216,7 @@ def kill_senators(self, game_id: int, senator_ids: List[int]) -> List[ActionLog]
self.assertEqual(
action_log.faction.position, matching_senator.faction.position
)
return latest_action_logs
return latest_action_logs, messages

def get_senators_with_title(
self, game_id: int, title_name: str | None
Expand Down
17 changes: 13 additions & 4 deletions backend/rorapp/views/submit_action.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from django.db import transaction
from django.http import HttpRequest
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rorapp.functions import face_mortality, select_faction_leader
from rorapp.functions import send_websocket_messages
from rorapp.models import Game, Faction, Step, Action


Expand All @@ -13,7 +15,7 @@ class SubmitActionViewSet(viewsets.ViewSet):

@action(detail=True, methods=["post"])
@transaction.atomic
def submit_action(self, request, game_id, action_id=None):
def submit_action(self, request: HttpRequest, game_id: int, action_id: int | None =None):
# Try to get the game
try:
game = Game.objects.get(id=game_id)
Expand Down Expand Up @@ -51,11 +53,18 @@ def submit_action(self, request, game_id, action_id=None):
{"message": "Action is not related to the current step"}, status=403
)

# Action-specific logic
return self.perform_action(game.id, action, request)

def perform_action(self, game_id: int, action: Action, request: HttpRequest) -> Response:
response = None
messages = None
match action.type:
case "select_faction_leader":
return select_faction_leader(action.id, request.data)
response, messages = select_faction_leader(action.id, request.data)
case "face_mortality":
return face_mortality(action.id)
response, messages = face_mortality(action.id)
case _:
return Response({"message": "Action type is invalid"}, status=400)

send_websocket_messages(game_id, messages)
return response
6 changes: 0 additions & 6 deletions backend/rorsite/middleware.py

This file was deleted.

Loading
Loading