Test draw application

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2023-04-09 00:50:47 +02:00
parent 80cfe874f5
commit 9734b51f53
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
3 changed files with 769 additions and 7 deletions

View File

@ -36,13 +36,6 @@ class DrawConsumer(AsyncJsonWebsocketConsumer):
"""
This consumer manages the websocket of the draw interface.
"""
def __int__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.tournament_id = None
self.tournament = None
self.participations = None
self.registration = None
async def connect(self) -> None:
"""
This function is called when a new websocket is trying to connect to the server.

View File

@ -206,6 +206,9 @@ class Round(models.Model):
help_text=_("The current pool where teams select their problems."),
)
def get_absolute_url(self):
return reverse_lazy('draw:index') + f'#{slugify(self.draw.tournament.name)}'
@property
def team_draws(self) -> QuerySet["TeamDraw"]:
"""
@ -278,6 +281,9 @@ class Pool(models.Model):
help_text=_("The full pool instance."),
)
def get_absolute_url(self):
return reverse_lazy('draw:index') + f'#{slugify(self.round.draw.tournament.name)}'
@property
def team_draws(self) -> QuerySet["TeamDraw"]:
"""
@ -483,6 +489,9 @@ class TeamDraw(models.Model):
verbose_name=_('rejected problems'),
)
def get_absolute_url(self):
return reverse_lazy('draw:index') + f'#{slugify(self.round.draw.tournament.name)}'
@property
def last_dice(self):
"""

View File

@ -1,2 +1,762 @@
# Copyright (C) 2023 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later
from random import shuffle
from asgiref.sync import sync_to_async
from channels.auth import AuthMiddlewareStack
from channels.routing import URLRouter
from channels.testing import WebsocketCommunicator
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.test import TestCase
from django.urls import reverse
from participation.models import Team, Tournament
from . import routing
from .models import Draw, Pool, Round, TeamDraw
class TestDraw(TestCase):
def setUp(self):
self.superuser = User.objects.create_superuser(
username="admin",
email="admin@example.com",
password="toto1234",
)
self.tournament = Tournament.objects.create(
name="Test",
)
self.teams = []
for i in range(12):
t = Team.objects.create(
name=f"Team {i + 1}",
trigram=3 * chr(65 + i),
)
t.participation.tournament = self.tournament
t.participation.valid = True
t.participation.save()
self.teams.append(t)
shuffle(self.teams)
async def test_draw(self): # noqa: C901
"""
Simulate a full draw operation.
"""
await sync_to_async(self.async_client.force_login)(self.superuser)
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Connect to Websocket
headers = [(b'cookie', self.async_client.cookies.output(header='', sep='; ').encode())]
communicator = WebsocketCommunicator(AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)),
f"/ws/draw/{self.tournament.id}/",
headers)
connected, subprotocol = await communicator.connect()
self.assertTrue(connected)
# Define language
await communicator.send_json_to({'type': 'set_language', 'language': 'en'})
# Ensure that Draw has not started
self.assertFalse(await Draw.objects.filter(tournament=self.tournament).aexists())
# Must be an error since 1+1+1 != 12
await communicator.send_json_to({'type': 'start_draw', 'fmt': '1+1+1'})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'alert')
self.assertEqual(resp['alert_type'], 'danger')
self.assertEqual(resp['message'], "The sum must be equal to the number of teams: expected 12, got 3")
self.assertFalse(await Draw.objects.filter(tournament=self.tournament).aexists())
# Now start the draw
await communicator.send_json_to({'type': 'start_draw', 'fmt': '3+4+5'})
# Receive data after the start
self.assertEqual((await communicator.receive_json_from())['type'], 'alert')
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_poules', 'round': 1,
'poules': [{'letter': 'A', 'teams': []},
{'letter': 'B', 'teams': []},
{'letter': 'C', 'teams': []}]})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_poules', 'round': 2,
'poules': [{'letter': 'A', 'teams': []},
{'letter': 'B', 'teams': []},
{'letter': 'C', 'teams': []}]})
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'alert')
self.assertEqual(await communicator.receive_json_from(),
{'type': 'draw_start', 'fmt': [5, 4, 3],
'trigrams': ['AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'FFF',
'GGG', 'HHH', 'III', 'JJJ', 'KKK', 'LLL']})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_active', 'round': 1, 'poule': None, 'team': None})
self.assertEqual((await communicator.receive_json_from())['type'], 'notification')
# Ensure that now tournament has started
self.assertTrue(await Draw.objects.filter(tournament=self.tournament).aexists())
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Try to relaunch the draw
await communicator.send_json_to({'type': 'start_draw', 'fmt': '3+4+5'})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'alert')
self.assertEqual(resp['alert_type'], 'danger')
self.assertEqual(resp['message'], "The draw is already started.")
draw: Draw = await Draw.objects.prefetch_related(
'current_round__current_pool__current_team__participation__team').aget(tournament=self.tournament)
r: Round = draw.current_round
for i, team in enumerate(self.teams):
# Launch a new dice
await communicator.send_json_to({'type': "dice", 'trigram': team.trigram})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], "dice")
self.assertEqual(resp['team'], team.trigram)
self.assertGreaterEqual(resp['result'], 1)
self.assertLessEqual(resp['result'], 100)
td: TeamDraw = await r.teamdraw_set.aget(participation=team.participation)
if i != len(self.teams) - 1:
self.assertEqual(resp['result'], td.passage_dice)
# Try to relaunch the dice
await communicator.send_json_to({'type': "dice", 'trigram': team.trigram})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'alert')
self.assertEqual(resp['message'], "You've already launched the dice.")
# Force exactly one duplicate
await td.arefresh_from_db()
td.passage_dice = 101 + i if i != 2 else 101
await td.asave()
# Manage duplicates
while dup_count := await r.teamdraw_set.filter(passage_dice__isnull=True).acount():
for i in range(dup_count):
# Dice
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'dice')
self.assertIsNone(resp['result'])
# Alert
self.assertEqual((await communicator.receive_json_from())['type'], 'alert')
for i in range(dup_count):
await communicator.send_json_to({'type': "dice", 'trigram': None})
await communicator.receive_json_from()
# Reset dices
for _i in range(12):
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'dice')
self.assertIsNone(resp['result'])
# Hide and re-display the dice
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': True})
# Set pools for the two rounds
self.assertEqual((await communicator.receive_json_from())['type'], 'set_poules')
self.assertEqual((await communicator.receive_json_from())['type'], 'set_poules')
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
# Manage the first pool
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_active', 'round': 1, 'poule': 'A', 'team': None})
r: Round = await Round.objects.prefetch_related('current_pool__current_team__participation__team')\
.aget(number=1, draw=draw)
p = r.current_pool
self.assertEqual(p.letter, 1)
self.assertEqual(p.size, 5)
self.assertEqual(await p.teamdraw_set.acount(), 5)
self.assertEqual(p.current_team, None)
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
i = 0
async for td in p.teamdraw_set.prefetch_related('participation__team').all():
# Launch a new dice
await communicator.send_json_to({'type': "dice", 'trigram': td.participation.team.trigram})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], "dice")
trigram = td.participation.team.trigram
self.assertEqual(resp['team'], trigram)
self.assertGreaterEqual(resp['result'], 1)
self.assertLessEqual(resp['result'], 100)
if i != p.size - 1:
await td.arefresh_from_db()
self.assertEqual(resp['result'], td.choice_dice)
# Try to relaunch the dice
await communicator.send_json_to({'type': "dice", 'trigram': trigram})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'alert')
self.assertEqual(resp['message'], "You've already launched the dice.")
# Force exactly one duplicate
await td.arefresh_from_db()
td.passage_dice = 101 + i if i != 1 else 101
await td.asave()
i += 1
# Manage duplicates
while dup_count := await p.teamdraw_set.filter(choice_dice__isnull=True).acount():
for i in range(dup_count):
# Dice
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'dice')
self.assertIsNone(resp['result'])
# Alert
self.assertEqual((await communicator.receive_json_from())['type'], 'alert')
for i in range(dup_count):
await communicator.send_json_to({'type': "dice", 'trigram': None})
await communicator.receive_json_from()
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
# Check current pool
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r, letter=1)
td = p.current_team
trigram = td.participation.team.trigram
self.assertEqual(td.choose_index, 0)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'A',
'team': td.participation.team.trigram})
# Dice is hidden for everyone first
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': False})
# The draw box is displayed for the current team and for volunteers
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Try to launch a dice while it is not the time
await communicator.send_json_to({'type': 'dice', 'trigram': None})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'alert')
self.assertEqual(resp['message'], "This is not the time for this.")
# Draw a problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
purposed = td.purposed
self.assertIsNotNone(td.purposed)
self.assertIn(td.purposed, range(1, len(settings.PROBLEMS) + 1))
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Try to redraw a problem while it is not the time
await communicator.send_json_to({'type': 'draw_problem'})
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'alert')
self.assertEqual(resp['message'], "This is not the time for this.")
# Reject the first problem
await communicator.send_json_to({'type': 'reject'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'reject_problem', 'round': 1, 'team': trigram, 'rejected': [purposed]})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
self.assertEqual(td.rejected, [purposed])
for i in range(4):
# Next team
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r, letter=1)
td = p.current_team
trigram = td.participation.team.trigram
self.assertEqual(td.choose_index, i + 1)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'A',
'team': trigram})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Draw a problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNotNone(td.purposed)
self.assertIn(td.purposed, range(1, len(settings.PROBLEMS) + 1))
# Assume that this is the problem 1 for teams 2 et 4 and the problem 2 for teams 3 and 5
td.purposed = 1 + (i % 2)
await td.asave()
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Accept the problem
await communicator.send_json_to({'type': 'accept'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_problem', 'round': 1, 'team': trigram, 'problem': 1 + (i % 2)})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
self.assertEqual(td.accepted, 1 + (i % 2))
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Go back to the first team of the pool
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r, letter=1)
td = p.current_team
trigram = td.participation.team.trigram
self.assertEqual(td.choose_index, 0)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'A',
'team': trigram})
# Draw and reject 100 times a problem
for _i in range(100):
# Draw a problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNotNone(td.purposed)
# Problems 1 and 2 are not available
self.assertIn(td.purposed, range(3, len(settings.PROBLEMS) + 1))
# Reject
await communicator.send_json_to({'type': 'reject'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': False})
self.assertEqual((await communicator.receive_json_from())['type'], 'reject_problem')
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
self.assertIn(purposed, td.rejected)
# Ensures that this is still the first team
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r, letter=1)
self.assertEqual(p.current_team, td)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'A',
'team': trigram})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Ensures that there is a penalty
self.assertGreaterEqual(td.penalty, 1)
# Draw a last problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNotNone(td.purposed)
self.assertIn(td.purposed, range(1, len(settings.PROBLEMS) + 1))
# Accept the problem
await communicator.send_json_to({'type': 'accept'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_problem', 'round': 1, 'team': trigram, 'problem': td.purposed})
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
# Reorder the pool since there are 5 teams
self.assertEqual((await communicator.receive_json_from())['type'], 'reorder_poule')
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_active', 'round': 1, 'poule': 'B', 'team': None})
# Start pool 2
r: Round = await Round.objects.prefetch_related('current_pool__current_team__participation__team')\
.aget(number=1, draw=draw)
p = r.current_pool
self.assertEqual(p.letter, 2)
self.assertEqual(p.size, 4)
self.assertEqual(await p.teamdraw_set.acount(), 4)
self.assertEqual(p.current_team, None)
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
i = 0
async for td in p.teamdraw_set.prefetch_related('participation__team').all():
# Launch a new dice
await communicator.send_json_to({'type': "dice", 'trigram': td.participation.team.trigram})
await communicator.receive_json_from()
await td.arefresh_from_db()
td.choice_dice = 101 + i # Avoid duplicates
await td.asave()
i += 1
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
for i in range(4):
# Next team
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r, letter=2)
td = p.current_team
trigram = td.participation.team.trigram
self.assertEqual(td.choose_index, i)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'B',
'team': trigram})
if i == 0:
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Draw a problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNotNone(td.purposed)
self.assertIn(td.purposed, range(1, len(settings.PROBLEMS) + 1))
# Lower problems are already accepted
self.assertGreaterEqual(td.purposed, i + 1)
# Assume that this is the problem is i for the team i
td.purposed = i + 1
await td.asave()
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Accept the problem
await communicator.send_json_to({'type': 'accept'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_problem', 'round': 1, 'team': trigram, 'problem': i + 1})
if i < 3:
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
else:
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
self.assertEqual(td.accepted, i + 1)
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Start pool 3
r: Round = await Round.objects.prefetch_related('current_pool__current_team__participation__team')\
.aget(number=1, draw=draw)
p = r.current_pool
self.assertEqual(p.letter, 3)
self.assertEqual(p.size, 3)
self.assertEqual(await p.teamdraw_set.acount(), 3)
self.assertEqual(p.current_team, None)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'C',
'team': None})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
i = 0
async for td in p.teamdraw_set.prefetch_related('participation__team').all():
# Launch a new dice
await communicator.send_json_to({'type': "dice", 'trigram': td.participation.team.trigram})
await communicator.receive_json_from()
await td.arefresh_from_db()
td.choice_dice = 101 + i # Avoid duplicates
await td.asave()
i += 1
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
for i in range(3):
# Next team
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r, letter=3)
td = p.current_team
trigram = td.participation.team.trigram
self.assertEqual(td.choose_index, i)
self.assertEqual(await communicator.receive_json_from(), {'type': 'set_active', 'round': 1, 'poule': 'C',
'team': trigram})
if i == 0:
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Draw a problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNotNone(td.purposed)
self.assertIn(td.purposed, range(1, len(settings.PROBLEMS) + 1))
# Lower problems are already accepted
self.assertGreaterEqual(td.purposed, i + 1)
# Assume that this is the problem is i for the team i
td.purposed = i + 1
await td.asave()
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Accept the problem
await communicator.send_json_to({'type': 'accept'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'buttons_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_problem', 'round': 1, 'team': trigram, 'problem': i + 1})
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
self.assertEqual(td.accepted, i + 1)
if i == 2:
break
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Start round 2
draw: Draw = await Draw.objects.prefetch_related(
'current_round__current_pool__current_team__participation__team').aget(tournament=self.tournament)
r = draw.current_round
p = r.current_pool
self.assertEqual(r.number, 2)
self.assertEqual(p.letter, 1)
for j in range(12):
# Reset dices
self.assertIsNone((await communicator.receive_json_from())['result'])
# Get pools
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'set_poules')
self.assertEqual(resp['round'], 2)
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': True})
self.assertEqual(await communicator.receive_json_from(), {'type': 'export_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
for i in range(3):
# Iterate on each pool
r: Round = await Round.objects.prefetch_related('current_pool__current_team__participation__team') \
.aget(draw=draw, number=2)
p = r.current_pool
self.assertEqual(p.letter, i + 1)
self.assertEqual(p.size, 5 - i)
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_active', 'round': 2, 'poule': chr(65 + i), 'team': None})
j = 0
async for td in p.teamdraw_set.prefetch_related('participation__team').all():
# Launch a new dice
await communicator.send_json_to({'type': "dice", 'trigram': td.participation.team.trigram})
await communicator.receive_json_from()
await td.arefresh_from_db()
td.choice_dice = 101 + j # Avoid duplicates
await td.asave()
j += 1
resp = await communicator.receive_json_from()
self.assertEqual(resp['type'], 'set_info')
for j in range(5 - i):
# Next team
p: Pool = await Pool.objects.prefetch_related('current_team__participation__team').aget(round=r,
letter=i + 1)
td = p.current_team
trigram = td.participation.team.trigram
self.assertEqual(td.choose_index, j)
self.assertEqual(await communicator.receive_json_from(),
{'type': 'set_active', 'round': 2, 'poule': chr(65 + i),
'team': trigram})
if j == 0:
self.assertEqual(await communicator.receive_json_from(),
{'type': 'dice_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'box_visibility', 'visible': True})
# Render page
resp = await self.async_client.get(reverse('draw:index'))
self.assertEqual(resp.status_code, 200)
# Draw a problem
await communicator.send_json_to({'type': 'draw_problem'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': False})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'buttons_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNotNone(td.purposed)
self.assertIn(td.purposed, range(1, len(settings.PROBLEMS) + 1))
# Check that the problem is different from the previous day
old_td = await TeamDraw.objects.aget(round__number=1, round__draw=draw,
participation_id=td.participation_id)
self.assertNotEqual(td.purposed, old_td.accepted)
# Accept the problem
await communicator.send_json_to({'type': 'accept'})
self.assertEqual(await communicator.receive_json_from(),
{'type': 'buttons_visibility', 'visible': False})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_problem')
td: TeamDraw = await TeamDraw.objects.prefetch_related('participation__team').aget(pk=td.pk)
self.assertIsNone(td.purposed)
if j == 4 - i:
break
self.assertEqual(await communicator.receive_json_from(), {'type': 'box_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
if i == 0:
# Reorder the pool since there are 5 teams
self.assertEqual((await communicator.receive_json_from())['type'], 'reorder_poule')
if i < 2:
self.assertEqual(await communicator.receive_json_from(), {'type': 'dice_visibility', 'visible': True})
else:
self.assertEqual(await communicator.receive_json_from(), {'type': 'export_visibility', 'visible': True})
self.assertEqual((await communicator.receive_json_from())['type'], 'set_info')
self.assertEqual((await communicator.receive_json_from())['type'], 'set_active')
# Export the draw
await communicator.send_json_to({'type': 'export'})
self.assertEqual(await communicator.receive_json_from(), {'type': 'export_visibility', 'visible': False})
# Cancel all steps and reset all
for i in range(1000):
await communicator.send_json_to({'type': 'cancel'})
if not await Draw.objects.filter(tournament=self.tournament).aexists():
break
else:
current_state = (await Draw.objects.filter(tournament=self.tournament).prefetch_related(
'current_round__current_pool__current_team__participation__team').aget()).get_state()
raise AssertionError("Draw wasn't aborted after 1000 steps, current state: " + current_state)
# Abort while the tournament is already aborted
await communicator.send_json_to({'type': "abort"})
def test_admin_pages(self):
"""
Check that admin pages are rendering successfully.
"""
self.client.force_login(self.superuser)
draw = Draw.objects.create(tournament=self.tournament)
r1 = Round.objects.create(draw=draw, number=1)
r2 = Round.objects.create(draw=draw, number=2)
p11 = Pool.objects.create(round=r1, letter=1, size=5)
p12 = Pool.objects.create(round=r1, letter=2, size=4)
p13 = Pool.objects.create(round=r1, letter=3, size=3)
p21 = Pool.objects.create(round=r2, letter=1, size=5)
p22 = Pool.objects.create(round=r2, letter=2, size=4)
p23 = Pool.objects.create(round=r2, letter=3, size=3)
tds = []
for i, team in enumerate(self.teams):
tds.append(TeamDraw.objects.create(participation=team.participation,
round=r1,
pool=p11 if i < 5 else p12 if i < 9 else p13))
tds.append(TeamDraw.objects.create(participation=team.participation,
round=r2,
pool=p21) if i < 5 else p22 if i < 9 else p23)
p11.current_team = tds[0]
p11.save()
r1.current_pool = p11
r1.save()
draw.current_round = r1
draw.save()
response = self.client.get(reverse("admin:index") + "draw/draw/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index")
+ f"draw/draw/{draw.pk}/change/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index") +
f"r/{ContentType.objects.get_for_model(Draw).id}/"
f"{draw.pk}/")
self.assertRedirects(response, "http://" + Site.objects.get().domain +
str(draw.get_absolute_url()), 302, 200)
response = self.client.get(reverse("admin:index") + "draw/round/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index")
+ f"draw/round/{r1.pk}/change/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index")
+ f"draw/round/{r2.pk}/change/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index") +
f"r/{ContentType.objects.get_for_model(Round).id}/"
f"{r1.pk}/")
self.assertRedirects(response, "http://" + Site.objects.get().domain +
str(r1.get_absolute_url()), 302, 200)
response = self.client.get(reverse("admin:index") + "draw/pool/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index")
+ f"draw/pool/{p11.pk}/change/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index") +
f"r/{ContentType.objects.get_for_model(Pool).id}/"
f"{p11.pk}/")
self.assertRedirects(response, "http://" + Site.objects.get().domain +
str(p11.get_absolute_url()), 302, 200)
response = self.client.get(reverse("admin:index") + "draw/teamdraw/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index")
+ f"draw/teamdraw/{tds[0].pk}/change/")
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("admin:index") +
f"r/{ContentType.objects.get_for_model(TeamDraw).id}/"
f"{tds[0].pk}/")
self.assertRedirects(response, "http://" + Site.objects.get().domain +
str(tds[0].get_absolute_url()), 302, 200)