Skip to content

Implement unit tests for progress-tracker contract (tests/unit/progress_tests.rs) #3

Description

@DeFiVC

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

  1. Create Env::default()
  2. Register and initialize: let contract_id = env.register(ProgressTracker, ()); then client.initialize(&admin);
  3. 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);
  1. 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.rsProgressInfo, Course, QuizResult
  • Constants: packages/shared/src/constants.rsMIN_CREDENTIAL_SCORE = 50, MAX_QUIZ_SCORE = 100

Metadata

Metadata

Assignees

No one assigned

    Labels

    good first issueGood for newcomersrustRust languagetestsTest additions or improvements

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions