Description
The file tests/unit/progress_tests.rs contains 10 test function skeletons for the progress-tracker contract. All assertions are commented out.
How to set up each test
- Create
Env::default()
- Register and initialize:
let contract_id = env.register(ProgressTracker, ()); then client.initialize(&admin);
- Create a course first before testing enrollment/progress:
let course_id = Symbol::new(&env, "rust_101");
let mut module_ids = Vec::new(&env);
module_ids.push_back(Symbol::new(&env, "mod_1"));
module_ids.push_back(Symbol::new(&env, "mod_2"));
module_ids.push_back(Symbol::new(&env, "mod_3"));
client.create_course(&course_id, &3, &2, &module_ids);
- Call
env.mock_all_auths();
Reference: inline tests at contracts/progress-tracker/src/lib.rs:285-419.
Tests to uncomment and complete
test_enrollment_creates_zero_progress
What it verifies: After enrollment, progress is 0%, not eligible, empty vectors.
client.enroll(&learner, &course_id);
let progress = client.get_progress(&learner, &course_id);
assert_eq!(progress.overall_progress, 0);
assert!(!progress.eligible_for_credential);
assert_eq!(progress.modules_completed.len(), 0);
assert_eq!(progress.quiz_scores.len(), 0);
test_module_completion_updates_progress
What it verifies: After completing 1 of 3 modules, modules_completed.len() is 1 and overall_progress > 0.
client.enroll(&learner, &course_id);
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_1"));
let progress = client.get_progress(&learner, &course_id);
assert_eq!(progress.modules_completed.len(), 1);
assert!(progress.overall_progress > 0);
test_quiz_submission_updates_progress
What it verifies: After submitting a quiz, quiz_scores.len() is 1 and the score is stored.
client.enroll(&learner, &course_id);
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_1"), &85);
let progress = client.get_progress(&learner, &course_id);
assert_eq!(progress.quiz_scores.len(), 1);
assert_eq!(progress.quiz_scores.get(0).unwrap().score, 85);
test_eligibility_requires_full_completion
What it verifies: After completing all 3 modules and submitting 2 quizzes with scores 80 and 70 (avg=75 >= 50), eligible_for_credential is true and overall_progress is 100.
client.enroll(&learner, &course_id);
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_1"));
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_2"));
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_3"));
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_1"), &80);
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_2"), &70);
let progress = client.get_progress(&learner, &course_id);
assert!(progress.eligible_for_credential);
assert_eq!(progress.overall_progress, 100);
test_eligibility_fails_with_low_quiz_scores
What it verifies: Even with all modules complete, if quiz avg is below 50 (e.g., scores 30 and 40, avg=35), eligible_for_credential is false.
client.enroll(&learner, &course_id);
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_1"));
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_2"));
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_3"));
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_1"), &30);
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_2"), &40);
let progress = client.get_progress(&learner, &course_id);
assert!(!progress.eligible_for_credential);
test_double_enrollment_rejected
What it verifies: #[should_panic(expected = "already enrolled")]
client.enroll(&learner, &course_id);
client.enroll(&learner, &course_id); // panics
test_double_module_completion_rejected
What it verifies: #[should_panic(expected = "module already completed")]
client.enroll(&learner, &course_id);
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_1"));
client.complete_module(&learner, &course_id, &Symbol::new(&env, "mod_1")); // panics
test_double_quiz_submission_rejected
What it verifies: #[should_panic(expected = "quiz already submitted")]
client.enroll(&learner, &course_id);
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_1"), &80);
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_1"), &90); // panics
test_quiz_score_above_max_rejected
What it verifies: #[should_panic(expected = "score exceeds maximum")]
client.enroll(&learner, &course_id);
client.submit_quiz_score(&learner, &course_id, &Symbol::new(&env, "quiz_1"), &101); // panics
test_get_progress_not_enrolled
What it verifies: #[should_panic(expected = "not enrolled")]
// Do NOT enroll the learner
client.get_progress(&learner, &course_id); // panics
test_admin_can_create_course
What it verifies: After create_course, get_course returns correct total_modules and total_quizzes.
client.create_course(&course_id, &3, &2, &module_ids);
let course = client.get_course(&course_id);
assert_eq!(course.total_modules, 3);
assert_eq!(course.total_quizzes, 2);
test_course_creation_rejects_mismatch
What it verifies: #[should_panic(expected = "module_ids length must match total_modules")]
let mut two_ids = Vec::new(&env);
two_ids.push_back(Symbol::new(&env, "mod_1"));
two_ids.push_back(Symbol::new(&env, "mod_2"));
client.create_course(&course_id, &3, &2, &two_ids); // panics: 2 != 3
Imports needed
use progress_tracker::{ProgressTracker, ProgressTrackerClient};
use soroban_sdk::{testutils::Address as _, Address, Env, Symbol, Vec};
How to run
cd chainlearn-contracts
cargo test --package progress-tracker --test progress_tests
References
- Contract source:
contracts/progress-tracker/src/lib.rs (420 lines)
- Progress calculation:
contracts/progress-tracker/src/rewards.rs — 70/30 weighted formula (line 20-48)
- Types:
contracts/progress-tracker/src/types.rs — ProgressInfo, Course, QuizResult
- Constants:
packages/shared/src/constants.rs — MIN_CREDENTIAL_SCORE = 50, MAX_QUIZ_SCORE = 100
Description
The file
tests/unit/progress_tests.rscontains 10 test function skeletons for theprogress-trackercontract. All assertions are commented out.How to set up each test
Env::default()let contract_id = env.register(ProgressTracker, ());thenclient.initialize(&admin);env.mock_all_auths();Reference: inline tests at
contracts/progress-tracker/src/lib.rs:285-419.Tests to uncomment and complete
test_enrollment_creates_zero_progressWhat it verifies: After enrollment, progress is 0%, not eligible, empty vectors.
test_module_completion_updates_progressWhat it verifies: After completing 1 of 3 modules,
modules_completed.len()is 1 andoverall_progress > 0.test_quiz_submission_updates_progressWhat it verifies: After submitting a quiz,
quiz_scores.len()is 1 and the score is stored.test_eligibility_requires_full_completionWhat it verifies: After completing all 3 modules and submitting 2 quizzes with scores 80 and 70 (avg=75 >= 50),
eligible_for_credentialis true andoverall_progressis 100.test_eligibility_fails_with_low_quiz_scoresWhat it verifies: Even with all modules complete, if quiz avg is below 50 (e.g., scores 30 and 40, avg=35),
eligible_for_credentialis false.test_double_enrollment_rejectedWhat it verifies:
#[should_panic(expected = "already enrolled")]test_double_module_completion_rejectedWhat it verifies:
#[should_panic(expected = "module already completed")]test_double_quiz_submission_rejectedWhat it verifies:
#[should_panic(expected = "quiz already submitted")]test_quiz_score_above_max_rejectedWhat it verifies:
#[should_panic(expected = "score exceeds maximum")]test_get_progress_not_enrolledWhat it verifies:
#[should_panic(expected = "not enrolled")]test_admin_can_create_courseWhat it verifies: After
create_course,get_coursereturns correcttotal_modulesandtotal_quizzes.test_course_creation_rejects_mismatchWhat it verifies:
#[should_panic(expected = "module_ids length must match total_modules")]Imports needed
How to run
References
contracts/progress-tracker/src/lib.rs(420 lines)contracts/progress-tracker/src/rewards.rs— 70/30 weighted formula (line 20-48)contracts/progress-tracker/src/types.rs—ProgressInfo,Course,QuizResultpackages/shared/src/constants.rs—MIN_CREDENTIAL_SCORE = 50,MAX_QUIZ_SCORE = 100