diff --git a/tests/unit/credential_tests.rs b/tests/unit/credential_tests.rs index cb1098e..f6868b8 100644 --- a/tests/unit/credential_tests.rs +++ b/tests/unit/credential_tests.rs @@ -330,4 +330,49 @@ mod credential_unit_tests { let info = client.verify_credential(&cred_id); assert_eq!(info.metadata_uri, valid_uri); } + + #[test] + fn test_renew_credential_extends_expiry() { + let env = Env::default(); + let (_admin, contract_id, tracker_id) = setup_contract(&env); + let client = CredentialNftClient::new(&env, &contract_id); + + let learner = Address::generate(&env); + env.mock_all_auths(); + + let course_id = Symbol::new(&env, "rust_101"); + enrolled_and_completed_with_score(&env, &tracker_id, &learner, &course_id, 90); + let metadata_uri = Symbol::new(&env, "ipfs_Qm123ValidURI"); + let cred_id = client.mint_credential(&learner, &course_id, &90, &metadata_uri); + + let before = client.verify_credential(&cred_id); + let new_expiry = before.expiry + 10_000; + + client.renew_credential(&cred_id, &new_expiry); + + let after = client.verify_credential(&cred_id); + assert_eq!(after.expiry, new_expiry); + assert!(after.expiry > before.expiry); + } + + #[test] + fn test_revoke_credential_with_reason_is_stored_and_queryable() { + let env = Env::default(); + let (_admin, contract_id, tracker_id) = setup_contract(&env); + let client = CredentialNftClient::new(&env, &contract_id); + + let learner = Address::generate(&env); + env.mock_all_auths(); + + let course_id = Symbol::new(&env, "rust_101"); + enrolled_and_completed_with_score(&env, &tracker_id, &learner, &course_id, 90); + let metadata_uri = Symbol::new(&env, "ipfs_Qm123ValidURI"); + let cred_id = client.mint_credential(&learner, &course_id, &90, &metadata_uri); + + let reason = Symbol::new(&env, "fraud_detected"); + client.revoke_credential_with_reason(&cred_id, &reason); + + let stored_reason = client.get_revocation_reason(&cred_id); + assert_eq!(stored_reason, Some(reason)); + } } diff --git a/tests/unit/progress_tests.rs b/tests/unit/progress_tests.rs index feae6e2..a23f537 100644 --- a/tests/unit/progress_tests.rs +++ b/tests/unit/progress_tests.rs @@ -1992,4 +1992,35 @@ mod progress_unit_tests { soroban_sdk::String::from_str(&env, "progress-tracker") ); } + + // ── Issue #299: course archiving ────────────────────────────────────── + + #[test] + fn test_archive_course_rejects_new_enrollments_but_preserves_progress() { + let env = Env::default(); + let (_admin, contract_id) = setup_contract(&env); + let client = ProgressTrackerClient::new(&env, &contract_id); + env.mock_all_auths(); + + let course_id = create_test_course(&env, &client); + + let existing_learner = Address::generate(&env); + client.enroll(&existing_learner, &course_id); + client.complete_module(&existing_learner, &course_id, &Symbol::new(&env, "mod_1")); + + let progress_before = client.get_progress(&existing_learner, &course_id); + + client.archive_course(&course_id); + + let new_learner = Address::generate(&env); + let result = client.try_enroll(&new_learner, &course_id); + assert!(result.is_err(), "enrollment on an archived course should be rejected"); + + let progress_after = client.get_progress(&existing_learner, &course_id); + assert_eq!( + progress_after.overall_progress, + progress_before.overall_progress, + "existing progress must be preserved after archiving" + ); + } } diff --git a/tests/unit/token_tests.rs b/tests/unit/token_tests.rs index 682e02b..56f88b7 100644 --- a/tests/unit/token_tests.rs +++ b/tests/unit/token_tests.rs @@ -638,4 +638,46 @@ mod token_unit_tests { .expect("expected a typed contract error, not a host trap"); assert_eq!(contract_err, learn_token::ContractError::AlreadyInitialized); } + + #[test] + fn test_governance_proposal_lifecycle() { + let env = Env::default(); + let (admin, contract_id, _) = setup_token(&env); + let client = LearnTokenClient::new(&env, &contract_id); + env.mock_all_auths(); + + let voter = Address::generate(&env); + client.mint(&admin, &voter, &1000); + + let snapshot_ledger = env.ledger().sequence(); + let proposal_id = client.create_proposal( + &SorobanString::from_str(&env, "Increase rewards"), + &2, + &0, + &1000, + &snapshot_ledger, + ); + + let proposal = client.get_proposal(&proposal_id).unwrap(); + assert_eq!(proposal.choices, 2); + assert!(!proposal.executed); + + // Voting power equals the voter's balance at the snapshot ledger. + assert_eq!(client.balance(&voter), 1000); + + client.vote(&voter, &proposal_id, &0); + + let after_vote = client.get_proposal(&proposal_id).unwrap(); + assert_eq!(after_vote.vote_totals.get(0).unwrap(), 1000); + + env.ledger().with_mut(|l| { + l.timestamp = 2000; + }); + + let winning_choice = client.execute_proposal(&proposal_id); + assert_eq!(winning_choice, 0); + + let executed = client.get_proposal(&proposal_id).unwrap(); + assert!(executed.executed); + } }