You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

182 lines
7.4 KiB

import tempfile
from unittest import mock
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import override_settings
from django.urls import reverse
from django.utils import timezone
from rest_framework import status
from rest_framework.test import APITestCase
from apps.account.models import ProfessorUser, StudentUser
from apps.course.models import (
Course,
CourseCategory,
CourseLiveSession,
Participant,
)
@override_settings(
PLUGNMEET_SERVER_URL='https://meet.example.com',
PLUGNMEET_API_KEY='test-key',
PLUGNMEET_API_SECRET='test-secret',
MEDIA_ROOT=tempfile.gettempdir(),
)
class CourseLiveSessionAPITests(APITestCase):
def setUp(self):
self.professor = ProfessorUser.objects.create(
email='prof@example.com',
fullname='Professor Sample',
experience_years=5,
)
self.student = StudentUser.objects.create(
email='student@example.com',
fullname='Student Sample',
)
self.category = CourseCategory.objects.create(name='Category', slug='category')
thumbnail = SimpleUploadedFile('thumb.jpg', b'filecontent', content_type='image/jpeg')
self.course = Course.objects.create(
title='Sample Course',
slug='sample-course',
category=self.category,
professor=self.professor,
thumbnail=thumbnail,
video_type=Course.VedioTypeChoices.YOUTUBE_LINK,
video_link='https://example.com/video',
is_online=True,
online_link='https://example.com/live',
level=Course.LevelChoices.BEGINNER,
duration=10,
lessons_count=2,
description='Description',
short_description='Short',
status=Course.StatusChoices.ONGOING,
is_free=True,
)
professor_avatar = SimpleUploadedFile('prof-avatar.jpg', b'avatar', content_type='image/jpeg')
self.professor.avatar = professor_avatar
self.professor.save(update_fields=['avatar'])
student_avatar = SimpleUploadedFile('student-avatar.jpg', b'avatar', content_type='image/jpeg')
self.student.avatar = student_avatar
self.student.save(update_fields=['avatar'])
@mock.patch('apps.course.views.live_session.PlugNMeetClient')
def test_professor_can_create_room(self, mock_client_cls):
mock_client = mock_client_cls.return_value
mock_client.create_room.return_value = {'status': 'success'}
self.client.force_authenticate(user=self.professor)
url = reverse('course-live-session-room-create', kwargs={'slug': self.course.slug})
payload = {
'room_id': 'custom-room-id',
'subject': 'Algebra Session',
}
response = self.client.post(url, payload, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
mock_client.create_room.assert_called_once()
self.assertTrue(
CourseLiveSession.objects.filter(course=self.course, room_id='custom-room-id').exists()
)
@mock.patch('apps.course.views.live_session.PlugNMeetClient')
def test_professor_receives_admin_token(self, mock_client_cls):
mock_client = mock_client_cls.return_value
mock_client.get_join_token.return_value = {'token': 'abc123'}
session = CourseLiveSession.objects.create(
course=self.course,
subject='Session',
started_at=timezone.now(),
room_id='room-123',
)
self.client.force_authenticate(user=self.professor)
url = reverse('course-live-session-token')
response = self.client.post(url, {'room_id': session.room_id}, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
args, _ = mock_client.get_join_token.call_args
payload = args[0]
self.assertTrue(payload['user_info']['is_admin'])
profile_pic = payload['user_info']['user_metadata'].get('profilePic')
self.assertEqual(profile_pic, f"http://testserver{self.professor.avatar.url}")
self.assertEqual(response.data['token'], 'abc123')
@mock.patch('apps.course.views.live_session.PlugNMeetClient')
def test_student_participant_receives_limited_token(self, mock_client_cls):
mock_client = mock_client_cls.return_value
mock_client.get_join_token.return_value = {'token': 'student-token'}
session = CourseLiveSession.objects.create(
course=self.course,
subject='Session',
started_at=timezone.now(),
room_id='room-456',
)
Participant.objects.create(course=self.course, student=self.student)
self.client.force_authenticate(user=self.student)
url = reverse('course-live-session-token')
response = self.client.post(url, {'room_id': session.room_id}, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
args, _ = mock_client.get_join_token.call_args
payload = args[0]
self.assertFalse(payload['user_info']['is_admin'])
metadata = payload['user_info']['user_metadata']
self.assertIn('lock_microphone', metadata['lock_settings'])
self.assertEqual(metadata.get('profilePic'), f"http://testserver{self.student.avatar.url}")
self.assertEqual(response.data['token'], 'student-token')
def test_student_without_access_cannot_get_token(self):
session = CourseLiveSession.objects.create(
course=self.course,
subject='Session',
started_at=timezone.now(),
room_id='room-789',
)
self.client.force_authenticate(user=self.student)
url = reverse('course-live-session-token')
response = self.client.post(url, {'room_id': session.room_id}, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_validate_metadata_includes_active_room_for_student(self):
session = CourseLiveSession.objects.create(
course=self.course,
subject='Session Live',
started_at=timezone.now(),
room_id='room-live-1',
)
Participant.objects.create(course=self.course, student=self.student)
self.client.force_authenticate(user=self.student)
url = reverse('course-online-validate', kwargs={'slug': self.course.slug})
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
metadata = response.data['metadata']
self.assertTrue(metadata['is_online'])
self.assertEqual(metadata['active_room_id'], session.room_id)
self.assertTrue(metadata['can_join_live_session'])
self.assertEqual(metadata['live_session']['room_id'], session.room_id)
self.assertIsNotNone(metadata['live_session']['started_at'])
def test_validate_metadata_for_professor_hides_creation_when_online(self):
CourseLiveSession.objects.create(
course=self.course,
subject='Session Live',
started_at=timezone.now(),
room_id='room-live-2',
)
self.client.force_authenticate(user=self.professor)
url = reverse('course-online-validate', kwargs={'slug': self.course.slug})
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
metadata = response.data['metadata']
self.assertFalse(metadata['can_create_live_session'])