feat: add Guided Learning Paths feature
Implement PathManager to orchestrate multi-module learning journeys: - Add PathManager class with start/pause/resume functionality - Create learning-paths.json config with CSS Fundamentals path - Integrate path progress tracking with LessonEngine - Add path selection UI to homepage and navigation - Include JSON schema for learning path validation - Add comprehensive test suite for PathManager
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, test, expect, vi, beforeEach } from "vitest";
|
||||
import { loadModules, getModuleById, loadModuleFromUrl, addCustomModule } from "../../src/config/lessons.js";
|
||||
import { loadModules, getModuleById, loadModuleFromUrl, addCustomModule, loadLearningPaths } from "../../src/config/lessons.js";
|
||||
|
||||
describe("Lessons Config Module", () => {
|
||||
describe("loadModules", () => {
|
||||
@@ -178,4 +178,86 @@ describe("Lessons Config Module", () => {
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadLearningPaths", () => {
|
||||
test("should return an array of learning paths", () => {
|
||||
const paths = loadLearningPaths();
|
||||
|
||||
expect(Array.isArray(paths)).toBe(true);
|
||||
expect(paths.length).toBeGreaterThanOrEqual(4);
|
||||
|
||||
// Check if paths have the right structure
|
||||
const pathIds = paths.map((p) => p.id);
|
||||
expect(pathIds).toContain("css-fundamentals");
|
||||
expect(pathIds).toContain("flexbox-master");
|
||||
expect(pathIds).toContain("html-forms-expert");
|
||||
expect(pathIds).toContain("css-animations-pro");
|
||||
});
|
||||
|
||||
test("should validate learning paths on load", () => {
|
||||
// This should not throw as paths are valid
|
||||
expect(() => loadLearningPaths()).not.toThrow();
|
||||
});
|
||||
|
||||
test("should resolve module references to actual module objects", () => {
|
||||
const paths = loadLearningPaths();
|
||||
|
||||
paths.forEach((path) => {
|
||||
expect(Array.isArray(path.modules)).toBe(true);
|
||||
expect(path.modules.length).toBeGreaterThan(0);
|
||||
|
||||
// Check that modules are actual objects, not just IDs
|
||||
path.modules.forEach((module) => {
|
||||
expect(typeof module).toBe("object");
|
||||
expect(module).not.toBeNull();
|
||||
expect(module.id).toBeDefined();
|
||||
expect(module.title).toBeDefined();
|
||||
expect(Array.isArray(module.lessons)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("should have required fields on each path", () => {
|
||||
const paths = loadLearningPaths();
|
||||
|
||||
paths.forEach((path) => {
|
||||
expect(path.id).toBeDefined();
|
||||
expect(path.title).toBeDefined();
|
||||
expect(path.goal).toBeDefined();
|
||||
expect(typeof path.estimatedTime).toBe("number");
|
||||
expect(path.estimatedTime).toBeGreaterThan(0);
|
||||
expect(["beginner", "intermediate", "advanced"]).toContain(path.difficulty);
|
||||
expect(Array.isArray(path.modules)).toBe(true);
|
||||
expect(path.modules.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
test("should support different languages", () => {
|
||||
const pathsEN = loadLearningPaths("en");
|
||||
const pathsDE = loadLearningPaths("de");
|
||||
|
||||
expect(Array.isArray(pathsEN)).toBe(true);
|
||||
expect(Array.isArray(pathsDE)).toBe(true);
|
||||
|
||||
// Both should have the same number of paths (structure is the same)
|
||||
expect(pathsEN.length).toBe(pathsDE.length);
|
||||
|
||||
// Modules should be resolved for each language
|
||||
pathsEN.forEach((path) => {
|
||||
expect(path.modules.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
pathsDE.forEach((path) => {
|
||||
expect(path.modules.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle missing modules gracefully", () => {
|
||||
const paths = loadLearningPaths();
|
||||
|
||||
// Should not throw even if some module references can't be resolved
|
||||
// (they are filtered out with a console warning)
|
||||
expect(Array.isArray(paths)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user