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
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'])
|