test: course package export and import

This commit is contained in:
Jannat Patel
2026-04-02 18:53:50 +05:30
parent c0df21c076
commit 55f01dc313
4 changed files with 83 additions and 6 deletions

View File

@@ -184,11 +184,8 @@ const exportCourse = async () => {
}
const blob = await response.blob()
// Extract filename from header if present
const disposition = response.headers.get('Content-Disposition')
let filename = 'course.zip'
if (disposition && disposition.includes('filename=')) {
filename = disposition.split('filename=')[1].replace(/"/g, '')
}

View File

@@ -173,7 +173,7 @@ const uploadFile = (e: Event) => {
const importZip = () => {
if (!zip.value) return
call('lms.lms.api.import_course_as_zip', {
call('lms.lms.api.import_course_from_zip', {
zip_file_path: zip.value.file_url,
})
.then((data: any) => {

View File

@@ -2375,6 +2375,6 @@ def export_course_as_zip(course_name: str):
@frappe.whitelist()
def import_course_as_zip(zip_file_path):
def import_course_from_zip(zip_file_path: str):
frappe.only_for(["Moderator", "Course Creator"])
return import_course_zip(zip_file_path)

View File

@@ -1,6 +1,16 @@
import glob
import os
import re
import zipfile
import frappe
from lms.lms.api import get_certified_participants, get_course_assessment_progress
from lms.lms.api import (
export_course_as_zip,
get_certified_participants,
get_course_assessment_progress,
import_course_from_zip,
)
from lms.lms.test_helpers import BaseTestUtils
@@ -83,3 +93,73 @@ class TestLMSAPI(BaseTestUtils):
)
self.assertEqual(result.is_correct, 1 if index % 2 == 0 else 0)
self.assertEqual(result.marks, 5 if index % 2 == 0 else 0)
def test_export_course_as_zip(self):
latest_file = self.get_latest_zip_file()
self.assertTrue(latest_file)
self.assertTrue(latest_file.endswith(".zip"))
expected_name_pattern = re.escape(self.course.name) + r"_\d{8}_\d{6}_[a-f0-9]{8}\.zip"
self.assertRegex(latest_file, expected_name_pattern)
with zipfile.ZipFile(latest_file, "r") as zip_ref:
expected_files = [
"course.json",
"instructors.json",
]
for expected_file in expected_files:
self.assertIn(expected_file, zip_ref.namelist())
chapter_files = [
f for f in zip_ref.namelist() if f.startswith("chapters/") and f.endswith(".json")
]
self.assertEqual(len(chapter_files), 3)
lesson_files = [f for f in zip_ref.namelist() if f.startswith("lessons/") and f.endswith(".json")]
self.assertEqual(len(lesson_files), 12)
assessment_files = [
f
for f in zip_ref.namelist()
if f.startswith("assessments/") and f.endswith(".json") and len(f.split("/")) == 2
]
self.assertEqual(len(assessment_files), 3)
def get_latest_zip_file(self):
export_course_as_zip(self.course.name)
site_path = frappe.get_site_path("private", "files")
zip_files = glob.glob(os.path.join(site_path, f"{self.course.name}_*.zip"))
latest_file = max(zip_files, key=os.path.getctime) if zip_files else None
return latest_file
def test_import_course_from_zip(self):
imported_course = self.get_imported_course()
self.assertEqual(imported_course.title, self.course.title)
self.assertEqual(imported_course.category, self.course.category)
# self.assertEqual(imported_course.lessons, self.course.lessons)
self.assertEqual(len(imported_course.instructors), len(self.course.instructors))
self.assertEqual(imported_course.instructors[0].instructor, self.course.instructors[0].instructor)
imported_first_chapter = frappe.get_doc("Course Chapter", self.course.chapters[0].chapter)
original_first_chapter = frappe.get_doc("Course Chapter", self.course.chapters[0].chapter)
self.assertEqual(imported_first_chapter.title, original_first_chapter.title)
imported_first_lesson = frappe.get_doc("Course Lesson", imported_first_chapter.lessons[0].lesson)
original_first_lesson = frappe.get_doc("Course Lesson", original_first_chapter.lessons[0].lesson)
self.assertEqual(imported_first_lesson.title, original_first_lesson.title)
self.assertEqual(imported_first_lesson.content, original_first_lesson.content)
self.cleanup_imported_course(imported_course.name)
def get_imported_course(self):
latest_file = self.get_latest_zip_file()
self.assertTrue(latest_file)
zip_file_path = f"/{latest_file.lstrip(frappe.get_site_path())}"
imported_course_name = import_course_from_zip(zip_file_path)
imported_course = frappe.get_doc("LMS Course", imported_course_name)
return imported_course
def cleanup_imported_course(self, course_name):
self.cleanup_items.append(("LMS Course", course_name))
self.cleanup_imported_assessment("LMS Quiz", self.quiz)
self.cleanup_imported_assessment("LMS Assignment", self.assignment)
self.cleanup_imported_assessment("LMS Programming Exercise", self.programming_exercise)
def cleanup_imported_assessment(self, doctype, doc):
imported_assessment = frappe.db.get_value(
doctype, {"title": doc.title, "name": ["!=", doc.name]}, "name"
)
if imported_assessment:
self.cleanup_items.append((doctype, imported_assessment))