summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yaksh/models.py2
-rw-r--r--yaksh/test_views.py494
-rw-r--r--yaksh/urls.py16
-rw-r--r--yaksh/views.py13
4 files changed, 493 insertions, 32 deletions
diff --git a/yaksh/models.py b/yaksh/models.py
index cc63615..ba092b8 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -163,7 +163,7 @@ class Profile(models.Model):
department = models.CharField(max_length=64)
position = models.CharField(max_length=64)
timezone = models.CharField(max_length=64,
- choices=[(tz, tz) for tz in pytz.common_timezones])
+ choices=[(tz, tz) for tz in pytz.common_timezones])
###############################################################################
diff --git a/yaksh/test_views.py b/yaksh/test_views.py
index 42b7f34..73a3f4f 100644
--- a/yaksh/test_views.py
+++ b/yaksh/test_views.py
@@ -1,4 +1,5 @@
from datetime import datetime
+import pytz
from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse
@@ -37,7 +38,8 @@ class TestProfile(TestCase):
roll_number=10,
institute='IIT',
department='Chemical',
- position='Student'
+ position='Student',
+ timezone='UTC'
)
def tearDown(self):
@@ -108,7 +110,8 @@ class TestProfile(TestCase):
'roll_number': 20,
'institute': 'new_institute',
'department': 'Aerospace',
- 'position': 'new_position'
+ 'position': 'new_position',
+ 'timezone': 'UTC'
}
)
updated_profile_user = User.objects.get(id=self.user2.id)
@@ -156,7 +159,8 @@ class TestAddQuiz(TestCase):
roll_number=10,
institute='IIT',
department='Chemical',
- position='Moderator'
+ position='Moderator',
+ timezone='UTC'
)
# Create Student
@@ -244,11 +248,12 @@ class TestAddQuiz(TestCase):
username=self.user.username,
password=self.user_plaintext_pass
)
+ tzone = pytz.timezone('UTC')
response = self.client.post(reverse('yaksh:edit_quiz',
kwargs={'quiz_id': self.quiz.id}),
data={
- 'start_date_time': datetime(2016, 1, 10, 9, 0, 15, 0),
- 'end_date_time': datetime(2016, 1, 15, 9, 0, 15, 0),
+ 'start_date_time': '2016-01-10 09:00:15', #datetime(2016, 1, 10, 9, 0, 15, 0, tzone),
+ 'end_date_time': '2016-01-15 09:00:15', #datetime(2016, 1, 15, 9, 0, 15, 0, tzone),
'duration': 30,
'active': False,
'attempts_allowed': 5,
@@ -263,10 +268,10 @@ class TestAddQuiz(TestCase):
updated_quiz = Quiz.objects.get(id=self.quiz.id)
self.assertEqual(updated_quiz.start_date_time,
- datetime(2016, 1, 10, 9, 0, 15, 0)
+ datetime(2016, 1, 10, 9, 0, 15, 0, tzone)
)
self.assertEqual(updated_quiz.end_date_time,
- datetime(2016, 1, 15, 9, 0, 15, 0)
+ datetime(2016, 1, 15, 9, 0, 15, 0, tzone)
)
self.assertEqual(updated_quiz.duration, 30)
self.assertEqual(updated_quiz.active, False)
@@ -289,10 +294,12 @@ class TestAddQuiz(TestCase):
username=self.user.username,
password=self.user_plaintext_pass
)
+
+ tzone = pytz.timezone('UTC')
response = self.client.post(reverse('yaksh:add_quiz'),
data={
- 'start_date_time': datetime(2016, 1, 10, 9, 0, 15, 0),
- 'end_date_time': datetime(2016, 1, 15, 9, 0, 15, 0),
+ 'start_date_time': '2016-01-10 09:00:15', #datetime(2016, 1, 10, 9, 0, 15, 0, tzone),
+ 'end_date_time': '2016-01-15 09:00:15', #datetime(2016, 1, 15, 9, 0, 15, 0, tzone),
'duration': 50,
'active': True,
'attempts_allowed': -1,
@@ -304,15 +311,13 @@ class TestAddQuiz(TestCase):
'course': self.course.id
}
)
-
-
quiz_list = Quiz.objects.all().order_by('-id')
new_quiz = quiz_list[0]
self.assertEqual(new_quiz.start_date_time,
- datetime(2016, 1, 10, 9, 0, 15, 0)
+ datetime(2016, 1, 10, 9, 0, 15, 0, tzone)
)
self.assertEqual(new_quiz.end_date_time,
- datetime(2016, 1, 15, 9, 0, 15, 0)
+ datetime(2016, 1, 15, 9, 0, 15, 0, tzone)
)
self.assertEqual(new_quiz.duration, 50)
self.assertEqual(new_quiz.active, True)
@@ -348,7 +353,8 @@ class TestAddTeacher(TestCase):
roll_number=10,
institute='IIT',
department='Chemical',
- position='Moderator'
+ position='Moderator',
+ timezone='UTC'
)
# Create Student
@@ -464,7 +470,8 @@ class TestAddTeacher(TestCase):
roll_number='T{}'.format(i),
institute='IIT',
department='Chemical',
- position='Teacher'
+ position='Teacher',
+ timezone='UTC'
)
teacher_id_list.append(teacher.id)
@@ -503,7 +510,8 @@ class TestRemoveTeacher(TestCase):
roll_number=10,
institute='IIT',
department='Chemical',
- position='Moderator'
+ position='Moderator',
+ timezone='UTC'
)
# Create Student
@@ -602,7 +610,8 @@ class TestRemoveTeacher(TestCase):
roll_number='RT{}'.format(i),
institute='IIT',
department='Aeronautical',
- position='Teacher'
+ position='Teacher',
+ timezone='UTC'
)
teacher_id_list.append(teacher.id)
self.course.teachers.add(teacher)
@@ -618,4 +627,453 @@ class TestRemoveTeacher(TestCase):
self.assertRedirects(response, redirect_destination)
for t_id in teacher_id_list:
teacher = User.objects.get(id=t_id)
- self.assertNotIn(teacher, self.course.teachers.all()) \ No newline at end of file
+ self.assertNotIn(teacher, self.course.teachers.all())
+
+
+class TestCourses(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ self.mod_group = Group.objects.create(name='moderator')
+
+ # Create Moderator with profile
+ self.user1_plaintext_pass = 'demo1'
+ self.user1 = User.objects.create_user(
+ username='demo_user1',
+ password=self.user1_plaintext_pass,
+ first_name='user1_first_name',
+ last_name='user1_last_name',
+ email='demo@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user1,
+ roll_number=10,
+ institute='IIT',
+ department='Chemical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ self.user2_plaintext_pass = 'demo2'
+ self.user2 = User.objects.create_user(
+ username='demo_user2',
+ password=self.user2_plaintext_pass,
+ first_name='user2_first_name',
+ last_name='user2_last_name',
+ email='demo2@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user2,
+ roll_number=10,
+ institute='IIT',
+ department='Aeronautical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ # Create Student
+ self.student_plaintext_pass = 'demo_student'
+ self.student = User.objects.create_user(
+ username='demo_student',
+ password=self.student_plaintext_pass,
+ first_name='student_first_name',
+ last_name='student_last_name',
+ email='demo_student@test.com'
+ )
+
+ # Add to moderator group
+ self.mod_group.user_set.add(self.user1)
+ self.mod_group.user_set.add(self.user2)
+
+ self.user1_course = Course.objects.create(name="Python Course",
+ enrollment="Enroll Request", creator=self.user1)
+
+ self.user2_course = Course.objects.create(name="Java Course",
+ enrollment="Enroll Request", creator=self.user2)
+
+ def tearDown(self):
+ self.client.logout()
+ self.user1.delete()
+ self.user2.delete()
+ self.student.delete()
+ self.user1_course.delete()
+ self.user2_course.delete()
+
+ def test_courses_denies_anonymous(self):
+ """
+ If not logged in redirect to login page
+ """
+ response = self.client.get(reverse('yaksh:courses'),
+ follow=True
+ )
+ redirect_destination = ('/exam/login/?next=%2Fexam'
+ '%2Fmanage%2Fcourses%2F')
+ self.assertRedirects(response, redirect_destination)
+
+ def test_courses_denies_non_moderator(self):
+ """
+ If not moderator redirect to login page
+ """
+ self.client.login(
+ username=self.student.username,
+ password=self.student_plaintext_pass
+ )
+
+ response = self.client.get(reverse('yaksh:courses'),
+ follow=True
+ )
+ self.assertEqual(response.status_code, 404)
+
+ def test_courses_get(self):
+ """
+ GET request should return courses page
+ """
+ self.client.login(
+ username=self.user1.username,
+ password=self.user1_plaintext_pass
+ )
+ response = self.client.get(reverse('yaksh:courses'),
+ follow=True
+ )
+
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'yaksh/courses.html')
+ self.assertIn(self.user1_course, response.context['courses'])
+ self.assertNotIn(self.user2_course, response.context['courses'])
+
+
+class TestCourseDetail(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ self.mod_group = Group.objects.create(name='moderator')
+
+ # Create Moderator with profile
+ self.user1_plaintext_pass = 'demo1'
+ self.user1 = User.objects.create_user(
+ username='demo_user1',
+ password=self.user1_plaintext_pass,
+ first_name='user1_first_name',
+ last_name='user1_last_name',
+ email='demo@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user1,
+ roll_number=10,
+ institute='IIT',
+ department='Chemical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ self.user2_plaintext_pass = 'demo2'
+ self.user2 = User.objects.create_user(
+ username='demo_user2',
+ password=self.user2_plaintext_pass,
+ first_name='user2_first_name',
+ last_name='user2_last_name',
+ email='demo2@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user2,
+ roll_number=10,
+ institute='IIT',
+ department='Aeronautical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ # Create Student
+ self.student_plaintext_pass = 'demo_student'
+ self.student = User.objects.create_user(
+ username='demo_student',
+ password=self.student_plaintext_pass,
+ first_name='student_first_name',
+ last_name='student_last_name',
+ email='demo_student@test.com'
+ )
+
+ # Add to moderator group
+ self.mod_group.user_set.add(self.user1)
+ self.mod_group.user_set.add(self.user2)
+
+ self.user1_course = Course.objects.create(name="Python Course",
+ enrollment="Enroll Request", creator=self.user1)
+
+ def tearDown(self):
+ self.client.logout()
+ self.user1.delete()
+ self.user2.delete()
+ self.student.delete()
+ self.user1_course.delete()
+
+ def test_course_detail_denies_anonymous(self):
+ """
+ If not logged in redirect to login page
+ """
+ response = self.client.get(reverse('yaksh:add_course'),
+ follow=True
+ )
+ redirect_destination = ('/exam/login/?next=%2Fexam'
+ '%2Fmanage%2Fadd_course%2F')
+ self.assertRedirects(response, redirect_destination)
+
+ def test_course_detail_denies_non_moderator(self):
+ """
+ If not moderator redirect to 404
+ """
+ self.client.login(
+ username=self.student.username,
+ password=self.student_plaintext_pass
+ )
+
+ response = self.client.get(reverse('yaksh:add_course'),
+ follow=True
+ )
+ self.assertEqual(response.status_code, 404)
+
+ def test_course_detail_denies_unrelated_moderators(self):
+ """
+ If not creator of course or related teacher redirect to 404
+ """
+ self.client.login(
+ username=self.user2.username,
+ password=self.user2_plaintext_pass
+ )
+ response = self.client.get(reverse('yaksh:course_detail',
+ kwargs={'course_id': self.user1_course.id}
+ ),
+ follow=True
+ )
+ self.assertEqual(response.status_code, 404)
+
+ def test_course_detail_get(self):
+ """
+ If not creator of course or related teacher redirect to 404
+ """
+ self.client.login(
+ username=self.user1.username,
+ password=self.user1_plaintext_pass
+ )
+ response = self.client.get(reverse('yaksh:course_detail',
+ kwargs={'course_id': self.user1_course.id}
+ ),
+ follow=True
+ )
+ self.assertEqual(self.user1_course, response.context['course'])
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'yaksh/course_detail.html')
+
+class TestEnrollRequest(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ self.mod_group = Group.objects.create(name='moderator')
+
+ # Create Moderator with profile
+ self.user1_plaintext_pass = 'demo1'
+ self.user1 = User.objects.create_user(
+ username='demo_user1',
+ password=self.user1_plaintext_pass,
+ first_name='user1_first_name',
+ last_name='user1_last_name',
+ email='demo@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user1,
+ roll_number=10,
+ institute='IIT',
+ department='Chemical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ self.user2_plaintext_pass = 'demo2'
+ self.user2 = User.objects.create_user(
+ username='demo_user2',
+ password=self.user2_plaintext_pass,
+ first_name='user2_first_name',
+ last_name='user2_last_name',
+ email='demo2@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user2,
+ roll_number=10,
+ institute='IIT',
+ department='Aeronautical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ # Create Student
+ self.student_plaintext_pass = 'demo_student'
+ self.student = User.objects.create_user(
+ username='demo_student',
+ password=self.student_plaintext_pass,
+ first_name='student_first_name',
+ last_name='student_last_name',
+ email='demo_student@test.com'
+ )
+
+ # Add to moderator group
+ self.mod_group.user_set.add(self.user1)
+ self.mod_group.user_set.add(self.user2)
+
+ self.course = Course.objects.create(name="Python Course",
+ enrollment="Enroll Request", creator=self.user1)
+
+ def tearDown(self):
+ self.client.logout()
+ self.user1.delete()
+ self.user2.delete()
+ self.student.delete()
+ self.course.delete()
+
+ def test_enroll_request_denies_anonymous(self):
+ """
+ If not logged in redirect to login page
+ """
+ response = self.client.get(reverse('yaksh:enroll_request',
+ kwargs={'course_id': self.course.id}
+ ),
+ follow=True
+ )
+ redirect_destination = ('/exam/login/?next=%2Fexam'
+ '%2Fenroll_request%2F{}%2F'.format(self.course.id))
+ self.assertRedirects(response, redirect_destination)
+
+ def test_enroll_request_get_for_student(self):
+ self.client.login(
+ username=self.student.username,
+ password=self.student_plaintext_pass
+ )
+
+ response = self.client.get(reverse('yaksh:enroll_request',
+ kwargs={'course_id': self.course.id}
+ ),
+ follow=True
+ )
+ self.assertRedirects(response, '/exam/quizzes/')
+
+ def test_enroll_request_get_for_moderator(self):
+ self.client.login(
+ username=self.user2.username,
+ password=self.user2_plaintext_pass
+ )
+
+ response = self.client.get(reverse('yaksh:enroll_request',
+ kwargs={'course_id': self.course.id}
+ ),
+ follow=True
+ )
+ self.assertRedirects(response, '/exam/manage/')
+
+
+class TestSelfEnroll(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ self.mod_group = Group.objects.create(name='moderator')
+
+ # Create Moderator with profile
+ self.user1_plaintext_pass = 'demo1'
+ self.user1 = User.objects.create_user(
+ username='demo_user1',
+ password=self.user1_plaintext_pass,
+ first_name='user1_first_name',
+ last_name='user1_last_name',
+ email='demo@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user1,
+ roll_number=10,
+ institute='IIT',
+ department='Chemical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ self.user2_plaintext_pass = 'demo2'
+ self.user2 = User.objects.create_user(
+ username='demo_user2',
+ password=self.user2_plaintext_pass,
+ first_name='user2_first_name',
+ last_name='user2_last_name',
+ email='demo2@test.com'
+ )
+
+ Profile.objects.create(
+ user=self.user2,
+ roll_number=10,
+ institute='IIT',
+ department='Aeronautical',
+ position='Moderator',
+ timezone='UTC'
+ )
+
+ # Create Student
+ self.student_plaintext_pass = 'demo_student'
+ self.student = User.objects.create_user(
+ username='demo_student',
+ password=self.student_plaintext_pass,
+ first_name='student_first_name',
+ last_name='student_last_name',
+ email='demo_student@test.com'
+ )
+
+ # Add to moderator group
+ self.mod_group.user_set.add(self.user1)
+ self.mod_group.user_set.add(self.user2)
+
+ self.course = Course.objects.create(name="Python Course",
+ enrollment="Enroll Request", creator=self.user1)
+
+ def tearDown(self):
+ self.client.logout()
+ self.user1.delete()
+ self.user2.delete()
+ self.student.delete()
+ self.course.delete()
+
+ def test_self_enroll_denies_anonymous(self):
+ response = self.client.get(reverse('yaksh:self_enroll',
+ kwargs={'course_id': self.course.id}
+ ),
+ follow=True
+ )
+ redirect_destination = ('/exam/login/?next=%2Fexam'
+ '%2Fself_enroll%2F{}%2F'.format(self.course.id))
+ self.assertRedirects(response, redirect_destination)
+
+ def test_enroll_request_get_for_student(self):
+ self.client.login(
+ username=self.student.username,
+ password=self.student_plaintext_pass
+ )
+
+ response = self.client.get(reverse('yaksh:self_enroll',
+ kwargs={'course_id': self.course.id}
+ ),
+ follow=True
+ )
+ self.assertRedirects(response, '/exam/quizzes/')
+
+ def test_enroll_request_get_for_moderator(self):
+ self.client.login(
+ username=self.user2.username,
+ password=self.user2_plaintext_pass
+ )
+
+ response = self.client.get(reverse('yaksh:self_enroll',
+ kwargs={'course_id': self.course.id}
+ ),
+ follow=True
+ )
+ self.assertRedirects(response, '/exam/manage/')
diff --git a/yaksh/urls.py b/yaksh/urls.py
index 3aff9a4..fa1713c 100644
--- a/yaksh/urls.py
+++ b/yaksh/urls.py
@@ -21,7 +21,7 @@ urlpatterns = [
urlpatterns += [
url(r'^$', views.index),
url(r'^login/$', views.user_login, name='login'),
- url(r'^quizzes/$', views.quizlist_user),
+ url(r'^quizzes/$', views.quizlist_user, name='quizlist_user'),
url(r'^results/$', views.results_user),
url(r'^start/$', views.start),
url(r'^start/(?P<questionpaper_id>\d+)/$', views.start),
@@ -38,9 +38,9 @@ urlpatterns += [
views.skip),
url(r'^(?P<q_id>\d+)/skip/(?P<next_q>\d+)/(?P<attempt_num>\d+)/(?P<questionpaper_id>\d+)/$',
views.skip),
- url(r'^enroll_request/(?P<course_id>\d+)/$', views.enroll_request),
- url(r'^self_enroll/(?P<course_id>\d+)/$', views.self_enroll),
- url(r'^manage/$', views.prof_manage),
+ url(r'^enroll_request/(?P<course_id>\d+)/$', views.enroll_request, name='enroll_request'),
+ url(r'^self_enroll/(?P<course_id>\d+)/$', views.self_enroll, name='self_enroll'),
+ url(r'^manage/$', views.prof_manage, name='manage'),
url(r'^manage/addquestion/$', views.add_question),
url(r'^manage/addquestion/(?P<question_id>\d+)/$', views.edit_question),
url(r'^manage/addquiz/$', views.add_quiz, name='add_quiz'),
@@ -67,9 +67,9 @@ urlpatterns += [
views.show_statistics),
url(r'^manage/monitor/download_csv/(?P<questionpaper_id>\d+)/$',
views.download_csv),
- url(r'manage/courses/$', views.courses),
- url(r'manage/add_course/$', views.add_course),
- url(r'manage/course_detail/(?P<course_id>\d+)/$', views.course_detail),
+ url(r'manage/courses/$', views.courses, name='courses'),
+ url(r'manage/add_course/$', views.add_course, name='add_course'),
+ url(r'manage/course_detail/(?P<course_id>\d+)/$', views.course_detail, name='course_detail'),
url(r'manage/enroll/(?P<course_id>\d+)/(?P<user_id>\d+)/$', views.enroll),
url(r'manage/enroll/rejected/(?P<course_id>\d+)/(?P<user_id>\d+)/$',
views.enroll, {'was_rejected': True}),
@@ -94,5 +94,3 @@ urlpatterns += [
url(r'^manage/upload_questions/$', views.show_all_questions),
url(r'^manage/(?P<mode>[\w\-]+)/(?P<quiz_id>\d+)/$', views.test_quiz)
]
-
-
diff --git a/yaksh/views.py b/yaksh/views.py
index 87e8bf6..56746b0 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -69,7 +69,7 @@ def get_user_dir(user):
def is_moderator(user):
"""Check if the user is having moderator rights"""
- if user.groups.filter(name='moderator').count() == 1:
+ if user.groups.filter(name='moderator').exists():
return True
def add_to_group(users):
@@ -219,7 +219,6 @@ def edit_question(request, question_id=None):
def add_quiz(request, quiz_id=None):
"""To add a new quiz in the database.
Create a new quiz and store it."""
-
user = request.user
ci = RequestContext(request)
if not is_moderator(user):
@@ -612,7 +611,10 @@ def enroll_request(request, course_id):
ci = RequestContext(request)
course = get_object_or_404(Course, pk=course_id)
course.request(user)
- return my_redirect('/exam/manage/')
+ if is_moderator(user):
+ return my_redirect('/exam/manage/')
+ else:
+ return my_redirect('/exam/quizzes/')
@login_required
@@ -623,7 +625,10 @@ def self_enroll(request, course_id):
if course.is_self_enroll():
was_rejected = False
course.enroll(was_rejected, user)
- return my_redirect('/exam/manage/')
+ if is_moderator(user):
+ return my_redirect('/exam/manage/')
+ else:
+ return my_redirect('/exam/quizzes/')
@login_required