Merge pull request #1998 from raizasafeel/fix/course-deletion
fix(course): resolve deletion failure for enrolled courses
This commit is contained in:
@@ -850,17 +850,18 @@ def get_announcements(batch):
|
||||
|
||||
@frappe.whitelist()
|
||||
def delete_course(course):
|
||||
chapters = frappe.get_all("Course Chapter", {"course": course}, pluck="name")
|
||||
frappe.db.delete("LMS Enrollment", {"course": course})
|
||||
frappe.db.delete("LMS Course Progress", {"course": course})
|
||||
frappe.db.set_value("LMS Quiz", {"course": course}, "course", None)
|
||||
frappe.db.set_value("LMS Quiz Submission", {"course": course}, "course", None)
|
||||
|
||||
chapter_references = frappe.get_all("Chapter Reference", {"parent": course}, pluck="name")
|
||||
chapters = frappe.get_all("Course Chapter", {"course": course}, pluck="name")
|
||||
frappe.db.delete("Chapter Reference", {"parent": course})
|
||||
|
||||
for chapter in chapters:
|
||||
lessons = frappe.get_all("Course Lesson", {"chapter": chapter}, pluck="name")
|
||||
|
||||
lesson_references = frappe.get_all("Lesson Reference", {"parent": chapter}, pluck="name")
|
||||
|
||||
for lesson in lesson_references:
|
||||
frappe.delete_doc("Lesson Reference", lesson)
|
||||
frappe.db.delete("Lesson Reference", {"parent": chapter})
|
||||
|
||||
for lesson in lessons:
|
||||
topics = frappe.get_all(
|
||||
@@ -871,21 +872,13 @@ def delete_course(course):
|
||||
|
||||
for topic in topics:
|
||||
frappe.db.delete("Discussion Reply", {"topic": topic})
|
||||
|
||||
frappe.db.delete("Discussion Topic", topic)
|
||||
|
||||
frappe.delete_doc("Course Lesson", lesson)
|
||||
|
||||
for chapter in chapter_references:
|
||||
frappe.delete_doc("Chapter Reference", chapter)
|
||||
|
||||
for chapter in chapters:
|
||||
frappe.delete_doc("Course Chapter", chapter)
|
||||
|
||||
frappe.db.delete("LMS Course Progress", {"course": course})
|
||||
frappe.db.delete("LMS Quiz", {"course": course})
|
||||
frappe.db.delete("LMS Quiz Submission", {"course": course})
|
||||
frappe.db.delete("LMS Enrollment", {"course": course})
|
||||
frappe.delete_doc("LMS Course", course)
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
# Copyright (c) 2022, Frappe and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.tests import UnitTestCase
|
||||
from frappe.utils import add_days, format_time, getdate
|
||||
|
||||
from lms.lms.doctype.course_evaluator.course_evaluator import get_schedule, get_schedule_range_end_date
|
||||
from lms.lms.test_utils import TestUtils
|
||||
from lms.lms.test_helpers import BaseTestUtils
|
||||
|
||||
|
||||
class TestCourseEvaluator(UnitTestCase):
|
||||
class TestCourseEvaluator(BaseTestUtils):
|
||||
def setUp(self):
|
||||
self.admin = TestUtils.create_user(
|
||||
self, "frappe@example.com", "Frappe", "Admin", ["Moderator", "Course Creator", "Batch Evaluator"]
|
||||
super().setUp()
|
||||
self.admin = self._create_user(
|
||||
"frappe@example.com", "Frappe", "Admin", ["Moderator", "Course Creator", "Batch Evaluator"]
|
||||
)
|
||||
self.course = TestUtils.create_a_course(self)
|
||||
|
||||
self.evaluator = TestUtils.create_evaluator(self)
|
||||
self.batch = TestUtils.create_a_batch(self)
|
||||
self.course = self._create_course()
|
||||
self.evaluator = self._create_evaluator()
|
||||
self.batch = self._create_batch(self.course.name)
|
||||
|
||||
def test_schedule_day_and_time(self):
|
||||
schedule = get_schedule(self.batch.courses[0].course, self.batch.name)
|
||||
|
||||
@@ -1,84 +1,55 @@
|
||||
# Copyright (c) 2021, FOSS United and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
|
||||
from .lms_course import LMSCourse
|
||||
from lms.lms.api import delete_course
|
||||
from lms.lms.test_helpers import BaseTestUtils
|
||||
|
||||
|
||||
class TestLMSCourse(unittest.TestCase):
|
||||
class TestLMSCourse(BaseTestUtils):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.instructor = self._create_user(
|
||||
"frappe@example.com", "Frappe", "Admin", ["Moderator", "Course Creator"]
|
||||
)
|
||||
|
||||
def test_new_course(self):
|
||||
course = new_course("Test Course")
|
||||
assert course.title == "Test Course"
|
||||
course_name = f"Test Course {frappe.generate_hash()}"
|
||||
|
||||
def tearDown(self):
|
||||
if frappe.db.exists("User", "tester@example.com"):
|
||||
frappe.delete_doc("User", "tester@example.com")
|
||||
course = self._create_course(course_name)
|
||||
|
||||
if frappe.db.exists("LMS Course", "test-course"):
|
||||
frappe.db.delete("Batch Course", {"course": "test-course"})
|
||||
frappe.db.delete("LMS Enrollment", {"course": "test-course"})
|
||||
frappe.db.delete("Course Lesson", {"course": "test-course"})
|
||||
frappe.db.delete("Course Chapter", {"course": "test-course"})
|
||||
frappe.db.delete("LMS Course Mentor Mapping", {"course": "test-course"})
|
||||
frappe.db.delete("Course Instructor", {"parent": "test-course"})
|
||||
frappe.db.sql("delete from `tabCourse Instructor`")
|
||||
frappe.delete_doc("LMS Course", "test-course")
|
||||
self.assertEqual(course.title, course_name)
|
||||
self.assertTrue(frappe.db.exists("LMS Course", course.name))
|
||||
|
||||
def test_delete_course(self):
|
||||
course = self._create_course(f"Test Course {frappe.generate_hash()}")
|
||||
chapter = self._create_chapter(f"Test Chapter {frappe.generate_hash()}", course.name)
|
||||
lesson = self._create_lesson(f"Test Lesson {frappe.generate_hash()}", chapter.name, course.name)
|
||||
|
||||
def new_user(name, email):
|
||||
user = frappe.db.exists("User", email)
|
||||
if user:
|
||||
return frappe.get_doc("User", user)
|
||||
else:
|
||||
filters = {
|
||||
"email": email,
|
||||
"first_name": name,
|
||||
"send_welcome_email": False,
|
||||
}
|
||||
lesson_ref = self._create_lesson_reference(chapter.name, lesson.name)
|
||||
chapter_ref = self._create_chapter_reference(course.name, chapter.name)
|
||||
|
||||
doc = frappe.new_doc("User")
|
||||
doc.update(filters)
|
||||
doc.save()
|
||||
return doc
|
||||
user_email = f"test_{frappe.generate_hash()}@example.com"
|
||||
self._create_user(user_email, "Test", "Member", ["LMS Student"])
|
||||
enrollment = self._create_enrollment(user_email, course.name)
|
||||
progress = self._create_progress(user_email, course.name, lesson.name)
|
||||
|
||||
delete_course(course.name)
|
||||
|
||||
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()
|
||||
user = frappe.db.get_value(
|
||||
"User",
|
||||
{
|
||||
"user_type": "System User",
|
||||
},
|
||||
)
|
||||
filters = {
|
||||
"title": title,
|
||||
"short_introduction": title,
|
||||
"description": title,
|
||||
"video_link": "https://youtu.be/pEbIhUySqbk",
|
||||
"image": "/assets/lms/images/course-home.png",
|
||||
"instructors": [{"instructor": user}],
|
||||
"published": 1,
|
||||
}
|
||||
self.assertFalse(frappe.db.exists("LMS Course", course.name))
|
||||
self.assertFalse(frappe.db.exists("Course Chapter", chapter.name))
|
||||
self.assertFalse(frappe.db.exists("Course Lesson", lesson.name))
|
||||
self.assertFalse(frappe.db.exists("LMS Enrollment", enrollment.name))
|
||||
self.assertFalse(frappe.db.exists("LMS Course Progress", {"course": course.name}))
|
||||
self.assertFalse(frappe.db.exists("Chapter Reference", {"parent": course.name}))
|
||||
self.assertFalse(frappe.db.exists("Lesson Reference", {"parent": chapter.name}))
|
||||
|
||||
if additional_filters:
|
||||
filters.update(additional_filters)
|
||||
|
||||
doc = frappe.new_doc("LMS Course")
|
||||
doc.update(filters)
|
||||
doc.save()
|
||||
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
|
||||
)
|
||||
# remove from cleanup_items list since delete_course already deleted them
|
||||
self.cleanup_items.remove(("LMS Course", course.name))
|
||||
self.cleanup_items.remove(("LMS Enrollment", enrollment.name))
|
||||
self.cleanup_items.remove(("LMS Course Progress", progress.name))
|
||||
self.cleanup_items.remove(("Chapter Reference", chapter_ref.name))
|
||||
self.cleanup_items.remove(("Lesson Reference", lesson_ref.name))
|
||||
self.cleanup_items.remove(("Course Chapter", chapter.name))
|
||||
self.cleanup_items.remove(("Course Lesson", lesson.name))
|
||||
|
||||
237
lms/lms/test_helpers.py
Normal file
237
lms/lms/test_helpers.py
Normal file
@@ -0,0 +1,237 @@
|
||||
import frappe
|
||||
from frappe.tests import UnitTestCase
|
||||
from frappe.utils import add_days, nowdate
|
||||
|
||||
from lms.lms.doctype.lms_certificate.lms_certificate import get_default_certificate_template
|
||||
|
||||
|
||||
class BaseTestUtils(UnitTestCase):
|
||||
"""
|
||||
Base class with helper methods for creating test data.
|
||||
Subclasses should call super().setUp() and super().tearDown().
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.cleanup_items = []
|
||||
|
||||
def tearDown(self):
|
||||
for item_type, item_name in reversed(self.cleanup_items):
|
||||
if frappe.db.exists(item_type, item_name):
|
||||
try:
|
||||
frappe.delete_doc(item_type, item_name, force=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _create_user(self, email, first_name, last_name, roles, user_type="Website User"):
|
||||
if frappe.db.exists("User", email):
|
||||
return frappe.get_doc("User", email)
|
||||
|
||||
user = frappe.new_doc("User")
|
||||
user.update(
|
||||
{
|
||||
"email": email,
|
||||
"first_name": first_name,
|
||||
"last_name": last_name,
|
||||
"user_type": user_type,
|
||||
"send_welcome_email": False,
|
||||
}
|
||||
)
|
||||
for role in roles:
|
||||
user.append("roles", {"role": role})
|
||||
user.save()
|
||||
self.cleanup_items.append(("User", user.name))
|
||||
return user
|
||||
|
||||
def _create_course(self, title="Utility Course", instructor="frappe@example.com"):
|
||||
existing = frappe.db.exists("LMS Course", {"title": title})
|
||||
if existing:
|
||||
return frappe.get_doc("LMS Course", existing)
|
||||
|
||||
course = frappe.new_doc("LMS Course")
|
||||
course.update(
|
||||
{
|
||||
"title": title,
|
||||
"short_introduction": "A course to test utilities of Frappe Learning",
|
||||
"description": "This is a detailed description of the Utility Course.",
|
||||
"tags": "Frappe,Learning,Utility",
|
||||
"published": 1,
|
||||
"instructors": [{"instructor": instructor}],
|
||||
}
|
||||
)
|
||||
course.save()
|
||||
self.cleanup_items.append(("LMS Course", course.name))
|
||||
return course
|
||||
|
||||
def _create_chapter(self, title, course):
|
||||
if not title:
|
||||
title = f"Course Chapter {frappe.generate_hash()}"
|
||||
|
||||
existing = frappe.db.exists("Course Chapter", {"course": course, "title": title})
|
||||
if existing:
|
||||
return frappe.get_doc("Course Chapter", existing)
|
||||
|
||||
chapter = frappe.new_doc("Course Chapter")
|
||||
chapter.update(
|
||||
{
|
||||
"course": course,
|
||||
"title": title,
|
||||
}
|
||||
)
|
||||
chapter.save()
|
||||
self.cleanup_items.append(("Course Chapter", chapter.name))
|
||||
return chapter
|
||||
|
||||
def _create_lesson(self, title, chapter, course):
|
||||
existing = frappe.db.exists("Course Lesson", {"course": course, "title": title})
|
||||
if existing:
|
||||
return frappe.get_doc("Course Lesson", existing)
|
||||
|
||||
lesson = frappe.new_doc("Course Lesson")
|
||||
lesson.update(
|
||||
{
|
||||
"course": course,
|
||||
"chapter": chapter,
|
||||
"title": title,
|
||||
"content": '{"time":1765194986690,"blocks":[{"id":"dkLzbW14ds","type":"markdown","data":{"text":"This is a simple content for the current lesson."}},{"id":"KBwuWPc8rV","type":"markdown","data":{"text":""}}],"version":"2.29.0"}',
|
||||
}
|
||||
)
|
||||
lesson.save()
|
||||
self.cleanup_items.append(("Course Lesson", lesson.name))
|
||||
return lesson
|
||||
|
||||
def _create_lesson_reference(self, chapter, lesson):
|
||||
lesson_ref = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Lesson Reference",
|
||||
"lesson": lesson,
|
||||
"parent": chapter,
|
||||
"parenttype": "Course Chapter",
|
||||
"parentfield": "lessons",
|
||||
"idx": 1,
|
||||
}
|
||||
)
|
||||
lesson_ref.insert()
|
||||
self.cleanup_items.append(("Lesson Reference", lesson_ref.name))
|
||||
return lesson_ref
|
||||
|
||||
def _create_chapter_reference(self, course, chapter, idx=1):
|
||||
chapter_ref = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Chapter Reference",
|
||||
"chapter": chapter,
|
||||
"parent": course,
|
||||
"parenttype": "LMS Course",
|
||||
"parentfield": "chapters",
|
||||
"idx": idx,
|
||||
}
|
||||
)
|
||||
chapter_ref.insert()
|
||||
self.cleanup_items.append(("Chapter Reference", chapter_ref.name))
|
||||
return chapter_ref
|
||||
|
||||
def _create_enrollment(self, member, course):
|
||||
existing = frappe.db.exists("LMS Enrollment", {"course": course, "member": member})
|
||||
if existing:
|
||||
return frappe.get_doc("LMS Enrollment", existing)
|
||||
|
||||
enrollment = frappe.new_doc("LMS Enrollment")
|
||||
enrollment.update({"member": member, "course": course})
|
||||
enrollment.insert()
|
||||
self.cleanup_items.append(("LMS Enrollment", enrollment.name))
|
||||
return enrollment
|
||||
|
||||
def _create_progress(self, member, course, lesson):
|
||||
progress = frappe.new_doc("LMS Course Progress")
|
||||
progress.update({"member": member, "course": course, "lesson": lesson})
|
||||
progress.insert()
|
||||
self.cleanup_items.append(("LMS Course Progress", progress.name))
|
||||
return progress
|
||||
|
||||
def _create_evaluator(self, evaluator_email="frappe@example.com"):
|
||||
if frappe.db.exists("Course Evaluator", evaluator_email):
|
||||
return frappe.get_doc("Course Evaluator", evaluator_email)
|
||||
|
||||
evaluator = frappe.new_doc("Course Evaluator")
|
||||
evaluator.update(
|
||||
{
|
||||
"evaluator": evaluator_email,
|
||||
"schedule": [
|
||||
{"day": "Monday", "start_time": "10:00", "end_time": "12:00"},
|
||||
{"day": "Wednesday", "start_time": "14:00", "end_time": "16:00"},
|
||||
],
|
||||
"unavailable_from": add_days(nowdate(), 5),
|
||||
"unavailable_to": add_days(nowdate(), 12),
|
||||
}
|
||||
)
|
||||
evaluator.save()
|
||||
self.cleanup_items.append(("Course Evaluator", evaluator.name))
|
||||
return evaluator
|
||||
|
||||
def _create_batch(
|
||||
self,
|
||||
course,
|
||||
instructor="frappe@example.com",
|
||||
title="Utility Training",
|
||||
evaluator="frappe@example.com",
|
||||
):
|
||||
existing = frappe.db.exists("LMS Batch", {"title": title})
|
||||
if existing:
|
||||
return frappe.get_doc("LMS Batch", existing)
|
||||
|
||||
batch = frappe.new_doc("LMS Batch")
|
||||
batch.update(
|
||||
{
|
||||
"title": title,
|
||||
"start_date": nowdate(),
|
||||
"end_date": add_days(nowdate(), 10),
|
||||
"start_time": "09:00:00",
|
||||
"end_time": "11:00:00",
|
||||
"timezone": "Asia/Kolkata",
|
||||
"description": "Batch for Utility Course Training",
|
||||
"batch_details": "This batch is created to test utility functions.",
|
||||
"evaluation_end_date": add_days(nowdate(), 120),
|
||||
"instructors": [{"instructor": instructor}],
|
||||
"courses": [{"course": course, "evaluator": evaluator}],
|
||||
}
|
||||
)
|
||||
batch.save()
|
||||
self.cleanup_items.append(("LMS Batch", batch.name))
|
||||
return batch
|
||||
|
||||
def _add_rating(self, course, member, rating, review_text):
|
||||
existing = frappe.db.exists("LMS Course Review", {"course": course, "owner": member})
|
||||
if existing:
|
||||
return frappe.get_doc("LMS Course Review", existing)
|
||||
|
||||
frappe.session.user = member
|
||||
review_doc = frappe.new_doc("LMS Course Review")
|
||||
review_doc.update(
|
||||
{
|
||||
"course": course,
|
||||
"rating": rating,
|
||||
"review": review_text,
|
||||
}
|
||||
)
|
||||
review_doc.save()
|
||||
self.cleanup_items.append(("LMS Course Review", review_doc.name))
|
||||
frappe.session.user = "Administrator"
|
||||
return review_doc
|
||||
|
||||
def _create_certificate(self, course, member):
|
||||
existing = frappe.db.exists("LMS Certificate", {"course": course, "member": member})
|
||||
if existing:
|
||||
return frappe.get_doc("LMS Certificate", existing)
|
||||
|
||||
certificate = frappe.new_doc("LMS Certificate")
|
||||
certificate.update(
|
||||
{
|
||||
"course": course,
|
||||
"member": member,
|
||||
"issue_date": frappe.utils.nowdate(),
|
||||
"template": get_default_certificate_template(),
|
||||
"published": 1,
|
||||
}
|
||||
)
|
||||
certificate.save()
|
||||
self.cleanup_items.append(("LMS Certificate", certificate.name))
|
||||
return certificate
|
||||
@@ -1,11 +1,12 @@
|
||||
# Copyright (c) 2021, FOSS United and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
from frappe.tests import UnitTestCase
|
||||
from frappe.utils import add_days, nowdate
|
||||
|
||||
from lms.lms.api import get_certified_participants
|
||||
from lms.lms.doctype.lms_certificate.lms_certificate import get_default_certificate_template, is_certified
|
||||
|
||||
from .utils import (
|
||||
from lms.lms.doctype.lms_certificate.lms_certificate import is_certified
|
||||
from lms.lms.test_helpers import BaseTestUtils
|
||||
from lms.lms.utils import (
|
||||
get_average_rating,
|
||||
get_chapters,
|
||||
get_evaluator,
|
||||
@@ -25,132 +26,50 @@ from .utils import (
|
||||
)
|
||||
|
||||
|
||||
class TestUtils(UnitTestCase):
|
||||
class TestLMSUtils(BaseTestUtils):
|
||||
def setUp(self):
|
||||
self.student1 = self.create_user("student1@example.com", "Ashley", "Smith", ["LMS Student"])
|
||||
self.student2 = self.create_user("student2@example.com", "John", "Doe", ["LMS Student"])
|
||||
self.admin = self.create_user(
|
||||
super().setUp()
|
||||
|
||||
self.student1 = self._create_user("student1@example.com", "Ashley", "Smith", ["LMS Student"])
|
||||
self.student2 = self._create_user("student2@example.com", "John", "Doe", ["LMS Student"])
|
||||
self.admin = self._create_user(
|
||||
"frappe@example.com", "Frappe", "Admin", ["Moderator", "Course Creator", "Batch Evaluator"]
|
||||
)
|
||||
self.course = self._create_course()
|
||||
self._setup_chapters_and_lessons()
|
||||
|
||||
self.course = self.create_a_course()
|
||||
self.add_chapters()
|
||||
self.add_lessons()
|
||||
self._create_enrollment(self.student1.email, self.course.name)
|
||||
self._create_enrollment(self.student2.email, self.course.name)
|
||||
|
||||
self.add_enrollment(self.course.name, self.student1.email)
|
||||
self.add_enrollment(self.course.name, self.student2.email)
|
||||
self._add_rating(self.course.name, self.student1.email, 0.8, "Good course")
|
||||
self._add_rating(self.course.name, self.student2.email, 1, "Excellent course")
|
||||
|
||||
self.add_rating(self.course.name, self.student1.email, 0.8, "Good course")
|
||||
self.add_rating(self.course.name, self.student2.email, 1, "Excellent course")
|
||||
self._create_certificate(self.course.name, self.student1.email)
|
||||
|
||||
self.create_certificate(self.course.name, self.student1.email)
|
||||
self.evaluator = self._create_evaluator()
|
||||
self.batch = self._create_batch(self.course.name)
|
||||
|
||||
self.evaluator = self.create_evaluator()
|
||||
self.batch = self.create_a_batch()
|
||||
|
||||
def create_a_course(self):
|
||||
existing_course = frappe.db.exists("LMS Course", {"title": "Utility Course"})
|
||||
if existing_course:
|
||||
return frappe.get_doc("LMS Course", existing_course)
|
||||
|
||||
course = frappe.new_doc("LMS Course")
|
||||
course.title = "Utility Course"
|
||||
course.short_introduction = "A course to test utilities of Frappe Learning"
|
||||
course.description = "This is a detailed description of the Utility Course."
|
||||
course.tags = "Frappe,Learning,Utility"
|
||||
course.published = 1
|
||||
course.append("instructors", {"instructor": "frappe@example.com"})
|
||||
course.save()
|
||||
return course
|
||||
|
||||
def add_chapters(self):
|
||||
def _setup_chapters_and_lessons(self):
|
||||
chapters = []
|
||||
for i in range(1, 4):
|
||||
chapter = frappe.new_doc("Course Chapter")
|
||||
chapter.course = self.course.name
|
||||
chapter.title = f"Chapter {i}"
|
||||
chapter.save()
|
||||
chapter = self._create_chapter(f"Chapter {i}", self.course.name)
|
||||
chapters.append(chapter)
|
||||
|
||||
self.course.reload()
|
||||
for chapter in chapters:
|
||||
self.course.append("chapters", {"chapter": chapter.name})
|
||||
if not any(c.chapter == chapter.name for c in self.course.chapters):
|
||||
self.course.append("chapters", {"chapter": chapter.name})
|
||||
self.course.save()
|
||||
|
||||
def add_lessons(self):
|
||||
for chapter in self.course.chapters:
|
||||
chapterDoc = frappe.get_doc("Course Chapter", chapter.chapter)
|
||||
lessons = []
|
||||
for chapter_ref in self.course.chapters:
|
||||
chapter_doc = frappe.get_doc("Course Chapter", chapter_ref.chapter)
|
||||
for j in range(1, 3):
|
||||
lesson = frappe.new_doc("Course Lesson")
|
||||
lesson.course = self.course.name
|
||||
lesson.chapter = chapter.chapter
|
||||
lesson.title = f"Lesson {j} of {chapter.chapter}"
|
||||
content = '{"time":1765194986690,"blocks":[{"id":"dkLzbW14ds","type":"markdown","data":{"text":"This is a simple content for the current lesson."}},{"id":"KBwuWPc8rV","type":"markdown","data":{"text":""}}],"version":"2.29.0"}'
|
||||
lesson.content = content
|
||||
lesson.save()
|
||||
lessons.append(lesson)
|
||||
lesson_title = f"Lesson {j} of {chapter_ref.chapter}"
|
||||
lesson = self._create_lesson(lesson_title, chapter_ref.chapter, self.course.name)
|
||||
|
||||
for lesson in lessons:
|
||||
chapterDoc.append("lessons", {"lesson": lesson.name})
|
||||
chapterDoc.save()
|
||||
|
||||
def create_evaluator(self):
|
||||
if frappe.db.exists("Course Evaluator", "frappe@example.com"):
|
||||
return frappe.get_doc("Course Evaluator", "frappe@example.com")
|
||||
|
||||
evaluator = frappe.new_doc("Course Evaluator")
|
||||
evaluator.evaluator = "frappe@example.com"
|
||||
evaluator.append("schedule", {"day": "Monday", "start_time": "10:00", "end_time": "12:00"})
|
||||
evaluator.append("schedule", {"day": "Wednesday", "start_time": "14:00", "end_time": "16:00"})
|
||||
evaluator.unavailable_from = add_days(nowdate(), 5)
|
||||
evaluator.unavailable_to = add_days(nowdate(), 12)
|
||||
evaluator.save()
|
||||
return evaluator
|
||||
|
||||
def create_a_batch(self):
|
||||
existing_batch = frappe.db.exists("LMS Batch", {"title": "Utility Training"})
|
||||
if existing_batch:
|
||||
return frappe.get_doc("LMS Batch", existing_batch)
|
||||
|
||||
batch = frappe.new_doc("LMS Batch")
|
||||
batch.title = "Utility Training"
|
||||
batch.start_date = nowdate()
|
||||
batch.end_date = add_days(batch.start_date, 10)
|
||||
batch.start_time = "09:00:00"
|
||||
batch.end_time = "11:00:00"
|
||||
batch.timezone = "Asia/Kolkata"
|
||||
batch.description = "Batch for Utility Course Training"
|
||||
batch.batch_details = "This batch is created to test utility functions."
|
||||
batch.evaluation_end_date = add_days(nowdate(), 120)
|
||||
batch.append("instructors", {"instructor": "frappe@example.com"})
|
||||
batch.append("courses", {"course": self.course.name, "evaluator": "frappe@example.com"})
|
||||
batch.save()
|
||||
return batch
|
||||
|
||||
def create_user(self, email, first_name, last_name, roles):
|
||||
if frappe.db.exists("User", email):
|
||||
return frappe.get_doc("User", email)
|
||||
else:
|
||||
user = frappe.new_doc("User")
|
||||
user.email = email
|
||||
user.first_name = first_name
|
||||
user.last_name = last_name
|
||||
user.user_type = "Website User"
|
||||
for role in roles:
|
||||
user.append("roles", {"role": role})
|
||||
user.save()
|
||||
return user
|
||||
|
||||
def create_certificate(self, course_name, member):
|
||||
certificate = frappe.new_doc("LMS Certificate")
|
||||
certificate.course = course_name
|
||||
certificate.member = member
|
||||
certificate.issue_date = frappe.utils.nowdate()
|
||||
certificate.template = get_default_certificate_template()
|
||||
certificate.published = 1
|
||||
certificate.save()
|
||||
return certificate
|
||||
if not any(l.lesson == lesson.name for l in chapter_doc.lessons):
|
||||
chapter_doc.append("lessons", {"lesson": lesson.name})
|
||||
chapter_doc.save()
|
||||
|
||||
def test_simple_slugs(self):
|
||||
self.assertEqual(slugify("hello-world"), "hello-world")
|
||||
@@ -161,12 +80,6 @@ class TestUtils(UnitTestCase):
|
||||
self.assertEqual(slugify("Hello World", ["hello-world"]), "hello-world-2")
|
||||
self.assertEqual(slugify("Hello World", ["hello-world", "hello-world-2"]), "hello-world-3")
|
||||
|
||||
def add_enrollment(self, course, member):
|
||||
enrollment = frappe.new_doc("LMS Enrollment")
|
||||
enrollment.course = course
|
||||
enrollment.member = member
|
||||
enrollment.save()
|
||||
|
||||
def test_get_membership(self):
|
||||
membership = get_membership(self.course.name, self.student1.email)
|
||||
self.assertIsNotNone(membership)
|
||||
@@ -185,13 +98,6 @@ class TestUtils(UnitTestCase):
|
||||
all_lessons = frappe.db.count("Course Lesson", {"course": self.course.name})
|
||||
self.assertEqual(len(lessons), all_lessons)
|
||||
|
||||
for chapter in self.course.chapters:
|
||||
chapter_lessons = [lesson for lesson in lessons if lesson.chapter == chapter.chapter]
|
||||
self.assertEqual(len(chapter_lessons), 2)
|
||||
for j, lesson in enumerate(chapter_lessons, start=1):
|
||||
self.assertEqual(lesson.title, f"Lesson {j} of {chapter.chapter}")
|
||||
self.assertEqual(lesson.number, f"{chapter.idx}-{j}")
|
||||
|
||||
def test_get_tags(self):
|
||||
tags = get_tags(self.course.name)
|
||||
expected_tags = ["Frappe", "Learning", "Utility"]
|
||||
@@ -206,27 +112,10 @@ class TestUtils(UnitTestCase):
|
||||
average_rating = get_average_rating(self.course.name)
|
||||
self.assertEqual(average_rating, 4.5)
|
||||
|
||||
def add_rating(self, course_name, member, rating, review):
|
||||
frappe.session.user = member
|
||||
review = frappe.new_doc("LMS Course Review")
|
||||
review.course = course_name
|
||||
review.rating = rating
|
||||
review.review = review
|
||||
review.save()
|
||||
frappe.session.user = "Administrator"
|
||||
|
||||
def test_get_reviews(self):
|
||||
reviews = get_reviews(self.course.name)
|
||||
self.assertEqual(len(reviews), 2)
|
||||
|
||||
for review in reviews:
|
||||
if review.rating == 0.8:
|
||||
self.assertEqual(review.member, self.student1.email)
|
||||
self.assertEqual(review.review, "Good course")
|
||||
elif review.rating == 1:
|
||||
self.assertEqual(review.member, self.student2.email)
|
||||
self.assertEqual(review.review, "Excellent course")
|
||||
|
||||
def test_get_lesson_index(self):
|
||||
lessons = get_lessons(self.course.name)
|
||||
for lesson in lessons:
|
||||
@@ -298,30 +187,16 @@ class TestUtils(UnitTestCase):
|
||||
frappe.db.set_value("User", self.student1.email, "open_to", "")
|
||||
|
||||
def test_rating_validation(self):
|
||||
student3 = self.create_user("student3@example.com", "Emily", "Cooper", ["LMS Student"])
|
||||
student3 = self._create_user("student3@example.com", "Emily", "Cooper", ["LMS Student"])
|
||||
with self.assertRaises(frappe.exceptions.ValidationError):
|
||||
self.add_rating(self.course.name, student3.email, -0.5, "Bad course")
|
||||
frappe.session.user = student3.email
|
||||
review = frappe.new_doc("LMS Course Review")
|
||||
review.course = self.course.name
|
||||
review.rating = -0.5
|
||||
review.review = "Bad course"
|
||||
review.save()
|
||||
frappe.session.user = "Administrator"
|
||||
frappe.delete_doc("User", student3.email)
|
||||
|
||||
def test_get_evaluator(self):
|
||||
evaluator_email = get_evaluator(self.course.name, self.batch.name)
|
||||
self.assertEqual(evaluator_email, self.evaluator.evaluator)
|
||||
|
||||
def tearDown(self):
|
||||
if frappe.db.exists("LMS Batch", self.batch.name):
|
||||
frappe.delete_doc("LMS Batch", self.batch.name)
|
||||
|
||||
if frappe.db.exists("LMS Course", self.course.name):
|
||||
frappe.db.delete("LMS Certificate", {"course": self.course.name})
|
||||
frappe.db.delete("LMS Enrollment", {"course": self.course.name})
|
||||
frappe.db.delete("LMS Course Review", {"course": self.course.name})
|
||||
frappe.db.delete("Course Lesson", {"course": self.course.name})
|
||||
frappe.db.delete("Course Chapter", {"course": self.course.name})
|
||||
frappe.db.delete("Course Instructor", {"parent": self.course.name})
|
||||
frappe.delete_doc("LMS Course", self.course.name)
|
||||
|
||||
frappe.delete_doc("Course Evaluator", self.evaluator.name)
|
||||
frappe.delete_doc("User", "student1@example.com")
|
||||
frappe.delete_doc("User", "student2@example.com")
|
||||
frappe.delete_doc("User", "frappe@example.com")
|
||||
|
||||
@@ -2,14 +2,13 @@ import frappe
|
||||
from frappe.tests.test_api import FrappeAPITestCase
|
||||
|
||||
from lms.auth import authenticate
|
||||
from lms.lms.test_utils import TestUtils
|
||||
from lms.lms.test_helpers import BaseTestUtils
|
||||
|
||||
|
||||
class TestAuth(FrappeAPITestCase):
|
||||
class TestAuth(BaseTestUtils, FrappeAPITestCase):
|
||||
def setUp(self):
|
||||
self.normal_user = TestUtils.create_user(
|
||||
self, "normal-user@example.com", "Normal", "User", ["LMS Student"]
|
||||
)
|
||||
super().setUp()
|
||||
self.normal_user = self._create_user("normal-user@example.com", "Normal", "User", ["LMS Student"])
|
||||
|
||||
def test_allowed_path(self):
|
||||
frappe.form_dict.cmd = "ping"
|
||||
@@ -24,4 +23,4 @@ class TestAuth(FrappeAPITestCase):
|
||||
frappe.session.user = "Administrator"
|
||||
|
||||
def tearDown(self):
|
||||
frappe.delete_doc("User", self.normal_user.name)
|
||||
super().tearDown()
|
||||
|
||||
Reference in New Issue
Block a user