test: evaluation eligibility

This commit is contained in:
Jannat Patel
2022-04-28 14:10:10 +05:30
parent bc6ae25aa6
commit 5db3d14b17
10 changed files with 140 additions and 106 deletions

View File

@@ -3,23 +3,16 @@
import frappe
import unittest
from lms.lms.doctype.lms_course.test_lms_course import new_course
class TestExercise(unittest.TestCase):
def setUp(self):
frappe.db.sql('delete from `tabLMS Batch Membership`')
frappe.db.sql('delete from `tabExercise Submission`')
frappe.db.sql('delete from `tabExercise`')
frappe.db.sql('delete from `tabLMS Course`')
def new_exercise(self):
course = frappe.get_doc({
"doctype": "LMS Course",
"name": "test-course",
"title": "Test Course",
"short_introduction": "Test Course",
"description": "Test Course"
})
course.insert()
course = new_course("Test Course")
member = frappe.get_doc({
"doctype": "LMS Batch Membership",
"course": course.name,

View File

@@ -5,27 +5,19 @@ from __future__ import unicode_literals
import frappe
import unittest
from lms.lms.doctype.lms_course.test_lms_course import new_user, new_course
class TestLMSBatchMembership(unittest.TestCase):
def setUp(self):
frappe.db.sql("DELETE FROM `tabLMS Batch Membership`")
frappe.db.sql("DELETE FROM `tabLMS Batch`")
frappe.db.sql('delete from `tabLMS Course Mentor Mapping`')
frappe.db.sql("DELETE FROM `tabLMS Course`")
frappe.db.sql("DELETE FROM `tabUser` where email like '%@test.com'")
def new_course_batch(self):
course = frappe.get_doc({
"doctype": "LMS Course",
"name": "test-course",
"title": "Test Course",
"short_code": "XX",
"short_introduction": "Test Course",
"description": "Test Course"
})
course.insert(ignore_permissions=True)
course = new_course("Test Course")
self.new_user("mentor@test.com", "Test Mentor")
new_user("Test Mentor", "mentor@test.com")
# without this, the creating batch will fail
course.add_mentor("mentor@test.com")
@@ -42,16 +34,6 @@ class TestLMSBatchMembership(unittest.TestCase):
frappe.session.user = "Administrator"
return course, batch
def new_user(self, email="test@test.com", full_name="Test User"):
user = frappe.get_doc({
"doctype": "User",
"name": email,
"email": email,
"first_name": full_name,
})
user.insert()
return user
def add_membership(self, batch_name, member_name, member_type="Student"):
doc = frappe.get_doc({
"doctype": "LMS Batch Membership",
@@ -64,7 +46,7 @@ class TestLMSBatchMembership(unittest.TestCase):
def test_membership(self):
course, batch = self.new_course_batch()
member = self.new_user("test01@test.com")
member = new_user("Test", "test01@test.com")
membership = self.add_membership(batch.name, member.name)
assert membership.course == course.name
@@ -72,7 +54,7 @@ class TestLMSBatchMembership(unittest.TestCase):
def test_membership_change_role(self):
course, batch = self.new_course_batch()
member = self.new_user("test01@test.com")
member = new_user("Test", "test01@test.com")
membership = self.add_membership(batch.name, member.name)
# it should be possible to change role

View File

@@ -10,7 +10,10 @@ from frappe.utils import nowdate, add_years, cint
class TestLMSCertificate(unittest.TestCase):
def test_certificate_creation(self):
course = new_course("Test Certificate", 1, 2)
course = new_course("Test Certificate", {
"enable_certification": 1,
"expiry": 2
})
certificate = create_certificate(course.name)
self.assertEqual(certificate.member, "Administrator")

View File

@@ -81,12 +81,13 @@
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"options": "Pass\nFail"
"options": "Pass\nFail",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2022-04-25 12:14:28.262851",
"modified": "2022-04-28 10:24:09.832428",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Certificate Evaluation",

View File

@@ -8,9 +8,6 @@ from .lms_course import LMSCourse
import unittest
class TestLMSCourse(unittest.TestCase):
def setUp(self):
frappe.db.sql('delete from `tabLMS Course Mentor Mapping`')
frappe.db.sql('delete from `tabLMS Course`')
def test_new_course(self):
course = new_course("Test Course")
@@ -34,21 +31,45 @@ class TestLMSCourse(unittest.TestCase):
frappe.delete_doc("User", "tester@example.com")
def new_user(name, email):
doc = frappe.get_doc(dict(
doctype='User',
email=email,
first_name=name))
user = frappe.db.exists("User", email)
if user:
return frappe.get_doc("User", user)
else:
filters = {
"doctype": "User",
"email": email,
"first_name": name,
"send_welcome_email": False
}
doc = frappe.get_doc(filters)
doc.insert()
return doc
def new_course(title, certificate=0, expiry=0):
doc = frappe.get_doc({
def new_course(title, additional_filters=None):
course = frappe.db.exists("LMS Course", { "title": title })
if course:
return frappe.get_doc("LMS Course", course)
else:
create_evaluator()
filters = {
"doctype": "LMS Course",
"title": title,
"short_introduction": title,
"description": title,
"enable_certificate": certificate,
"expiry": expiry
})
"description": title
}
if additional_filters:
filters.update(additional_filters)
doc = frappe.get_doc(filters)
doc.insert(ignore_permissions=True)
return doc
def create_evaluator():
if not frappe.db.exists("Course Evaluator", "evaluator@example.com"):
new_user("Evaluator", "evaluator@example.com")
frappe.get_doc({
"doctype": "Course Evaluator",
"evaluator": "evaluator@example.com"
}).save(ignore_permissions=True)

View File

@@ -1,7 +1,10 @@
import unittest
from .utils import slugify
import frappe
from .utils import slugify, get_evaluation_details
from lms.lms.doctype.lms_course.test_lms_course import new_course, new_user
from frappe.utils import getdate
class TestSlugify(unittest.TestCase):
class TestUtils(unittest.TestCase):
def test_simple(self):
self.assertEquals(slugify("hello-world"), "hello-world")
self.assertEquals(slugify("Hello World"), "hello-world")
@@ -15,3 +18,50 @@ class TestSlugify(unittest.TestCase):
self.assertEquals(
slugify("Hello World", ['hello-world', 'hello-world-2']),
"hello-world-3")
def test_evaluation_details(self):
course = new_course("Test Evaluation Details", {
"enable_certification": 1,
"grant_certificate_after": "Evaluation",
"evaluator": "evaluator@example.com",
"max_attempts": 3,
"reapplication": 2
})
user = new_user("Eval", "eval@test.com")
# Two evaluations failed within max attempts. Check eligibility for a third evaluation
create_evaluation(user.name, course.name, getdate("21-03-2022"), 0.4, "Fail")
create_evaluation(user.name, course.name, getdate("12-04-2022"), 0.4, "Fail")
details = get_evaluation_details(course.name, user.name)
self.assertTrue(details.eligible)
# Three evaluations failed within max attempts. Check eligibility for a forth evaluation
create_evaluation(user.name, course.name, getdate("21-03-2022"), 0.4, "Fail")
create_evaluation(user.name, course.name, getdate("12-04-2022"), 0.4, "Fail")
create_evaluation(user.name, course.name, getdate("16-04-2022"), 0.4, "Fail")
details = get_evaluation_details(course.name, user.name)
self.assertFalse(details.eligible)
# Three evaluations failed within max attempts. Check eligibility for a forth evaluation. Different Dates
create_evaluation(user.name, course.name, getdate("01-03-2022"), 0.4, "Fail")
create_evaluation(user.name, course.name, getdate("12-04-2022"), 0.4, "Fail")
create_evaluation(user.name, course.name, getdate("16-04-2022"), 0.4, "Fail")
details = get_evaluation_details(course.name, user.name)
self.assertFalse(details.eligible)
frappe.db.delete("LMS Certificate Evaluation", {"course": course.name})
frappe.db.delete("LMS Course", course.name)
frappe.db.delete("User", user.name)
def create_evaluation(user, course, date, rating, status):
evaluation = frappe.get_doc({
"doctype": "LMS Certificate Evaluation",
"member": user,
"course": course,
"date": date,
"start_time": "12:00:00",
"end_time": "13:00:00",
"rating": rating,
"status": status
})
evaluation.save(ignore_permissions=True)

View File

@@ -1,6 +1,6 @@
import re
import frappe
from frappe.utils import flt, cint, cstr
from frappe.utils import flt, cint, cstr, getdate, add_months
from lms.lms.md import markdown_to_html, find_macros
import string
from frappe import _
@@ -345,25 +345,24 @@ def get_popular_courses():
course_membership = sorted(course_membership, key = lambda x: x.get("members"), reverse=True)
return course_membership[:3]
def get_evaluation_details(course):
info = frappe.db.get_value("LMS Course", course, ["grant_certificate_after", "max_attempts"], as_dict=True)
def get_evaluation_details(course, member=None):
info = frappe.db.get_value("LMS Course", course, ["grant_certificate_after", "max_attempts", "reapplication"], as_dict=True)
request = frappe.db.get_value("LMS Certificate Request", {
"course": course.name,
"member": frappe.session.user,
"course": course,
"member": member or frappe.session.user,
"date": [">=", getdate()]
}, ["date", "start_time", "end_time"],
as_dict=True)
no_of_attempts = frappe.db.count("LMS Certificate Evaluation", {
"course": course.name,
"member": frappe.session.user,
"course": course,
"member": member or frappe.session.user,
"status": ["!=", "Pass"],
"creation": [">=", add_months(getdate(), -2)]
"creation": [">=", add_months(getdate(), -abs(cint(info.reapplication)))]
})
return {
return frappe._dict({
"eligible": info.grant_certificate_after == "Evaluation" and not request and no_of_attempts < info.max_attempts,
"request": request,
"no_of_attempts": no_of_attempts
}
})

View File

@@ -1,55 +1,36 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
import frappe
from lms.lms.doctype.lms_course.test_lms_course import new_user
class TestCustomUser(unittest.TestCase):
def test_with_basic_username(self):
new_user = frappe.get_doc({
"doctype": "User",
"email": "test_with_basic_username@example.com",
"first_name": "Username"
}).insert(ignore_permissions=True)
self.assertEqual(new_user.username, "username")
user = new_user("Username", "test_with_basic_username@example.com")
self.assertEqual(user.username, "username")
def test_without_username(self):
""" The user in this test has the same first name as the user of the test test_with_basic_username.
In such cases frappe makes the username of the second user empty.
The condition in lms app should override this and save a username. """
new_user = frappe.get_doc({
"doctype": "User",
"email": "test-without-username@example.com",
"first_name": "Username"
}).insert(ignore_permissions=True)
self.assertTrue(new_user.username)
user = new_user("Username", "test-without-username@example.com")
self.assertTrue(user.username)
def test_with_illegal_characters(self):
new_user = frappe.get_doc({
"doctype": "User",
"email": "test_with_illegal_characters@example.com",
"first_name": "Username$$"
}).insert(ignore_permissions=True)
self.assertEqual(new_user.username[:8], "username")
user = new_user("Username$$", "test_with_illegal_characters@example.com")
self.assertEqual(user.username[:8], "username")
def test_with_underscore_at_end(self):
new_user = frappe.get_doc({
"doctype": "User",
"email": "test_with_underscore_at_end@example.com",
"first_name": "Username___"
}).insert(ignore_permissions=True)
self.assertNotEqual(new_user.username[-1], "_")
user = new_user("Username___", "test_with_underscore_at_end@example.com")
self.assertNotEqual(user.username[-1], "_")
def test_with_short_first_name(self):
new_user = frappe.get_doc({
"doctype": "User",
"email": "test_with_short_first_name@example.com",
"first_name": "USN"
}).insert(ignore_permissions=True)
self.assertGreaterEqual(len(new_user.username), 4)
user = new_user("USN", "test_with_short_first_name@example.com")
self.assertGreaterEqual(len(user.username), 4)
@classmethod
def tearDownClass(cls) -> None:

View File

@@ -117,6 +117,10 @@
</div>
{% endif %}
{% if no_of_attempts >= course.max_attempts %}
<p> {{ _("You have exceeded the maximum number of attempts allowed to appear for evaluations of this course.") }} </p>
{% endif %}
{% if is_instructor(course.name) %}
<div class="vertically-center mb-4">
<a class="button is-default button-links mr-2" href="/course?name={{ course.name }}"> {{ _("Edit") }} </a>
@@ -204,13 +208,11 @@
<a class="button wide-button is-secondary mt-2" href="/courses/{{ course.name }}/{{ certificate }}">
{{ _("Get Certificate") }}
</a>
{% elif eligible_for_evaluation %}
{% elif eligible %}
<a class="button wide-button is-secondary mt-2" id="apply-certificate" data-course="{{ course.name }}">
{{ _("Apply for Certificate") }}
</a>
{% elif no_of_attempts < course.max_attempt %}
<p> {{ _("You have exceeded the maximum number of attempts allowed to appear for evaluations for this course.") }} </p>
{% elif progress == 100 %}
{% elif course.grant_certificate_after == "Completion" and progress == 100 %}
<div class="button wide-button is-secondary mt-4" id="certification" data-course="{{ course.name }}">
{{ _("Get Certificate") }}
</div>

View File

@@ -1,6 +1,6 @@
import frappe
from lms.lms.doctype.lms_settings.lms_settings import check_profile_restriction
from lms.lms.utils import get_membership, is_instructor, is_certified, eligible_for_certificate_evaluation
from lms.lms.utils import get_membership, is_instructor, is_certified, get_evaluation_details
from frappe.utils import add_months, getdate
def get_context(context):
@@ -35,8 +35,10 @@ def get_context(context):
context.restriction = check_profile_restriction()
context.show_start_learing_cta = show_start_learing_cta(course, membership, context.restriction)
context.certificate = is_certified(course.name)
context.eligible_for_evaluation = eligible_for_certificate_evaluation()
context.certificate_request =
eval_details = get_evaluation_details(course.name)
context.eligible_for_evaluation = eval_details.eligible
context.certificate_request = eval_details.request
context.no_of_attempts = eval_details.no_of_attempts
if context.course.upcoming:
context.is_user_interested = get_user_interest(context.course.name)