Skip to content

Implement integration tests: fixtures + token/credential flow tests #4

Description

@DeFiVC

Description

The tests/integration/ directory has 3 files where all contract interaction logic is commented out:

  • fixtures.rs — Uses placeholder Address::generate() instead of real contract registration
  • token_flow.rs — 5 end-to-end tests with commented-out assertions
  • credential_flow.rs — 6 end-to-end tests with commented-out assertions

This issue requires wiring up real contracts in the fixtures and completing all 11 integration tests.

Step 1: Fix fixtures.rs

The current setup_chainlearn_env() (line 21-53) generates placeholder addresses. Replace with real contract registration:

pub fn setup_chainlearn_env() -> ChainLearnEnv {
    let env = Env::default();
    let admin = Address::generate(&env);
    let learner = Address::generate(&env);

    // Register and initialize LearnToken
    let token_contract_id = env.register(learn_token::LearnToken, ());
    let token_client = learn_token::LearnTokenClient::new(&env, &token_contract_id);
    token_client.initialize(
        &admin,
        &Symbol::new(&env, "CLearn"),
        &Symbol::new(&env, "CLRN"),
        &7,
    );

    // Register and initialize CredentialNft
    let credential_contract_id = env.register(credential_nft::CredentialNft, ());
    let credential_client = credential_nft::CredentialNftClient::new(&env, &credential_contract_id);
    credential_client.initialize(&admin);

    // Register and initialize ProgressTracker
    let progress_contract_id = env.register(progress_tracker::ProgressTracker, ());
    let progress_client = progress_tracker::ProgressTrackerClient::new(&env, &progress_contract_id);
    progress_client.initialize(&admin);

    ChainLearnEnv {
        env,
        admin,
        learner,
        token_contract_id,
        credential_contract_id,
        progress_contract_id,
    }
}

Also update create_sample_course (line 58-71) to use the real progress client:

pub fn create_sample_course(env: &Env, client: &progress_tracker::ProgressTrackerClient) -> Symbol {
    let course_id = Symbol::new(env, "rust_101");
    let mut module_ids = Vec::new(env);
    module_ids.push_back(Symbol::new(env, "mod_basics"));
    module_ids.push_back(Symbol::new(env, "mod_ownership"));
    module_ids.push_back(Symbol::new(env, "mod_traits"));
    client.create_course(&course_id, &3, &2, &module_ids);
    course_id
}

And complete_full_course (line 76-89) to use real calls.

You'll need to add these imports to fixtures.rs:

use soroban_sdk::Vec;

And add pub visibility to the client fields in ChainLearnEnv or return clients alongside the env.

Step 2: Implement token_flow.rs (5 tests)

Each test should use fixtures::setup_chainlearn_env(), create clients from the stored contract IDs, and call env.mock_all_auths().

test_end_to_end_reward_flow

  1. Create course via progress client
  2. Enroll learner
  3. Complete all 3 modules (mod_basics, mod_ownership, mod_traits)
  4. Submit quiz score (85)
  5. Claim reward via token client: token_client.claim_reward(learner, &quiz_id, &85)
  6. Assert: reward = 8500, balance = 8500

test_double_claim_prevented

  1. Claim reward for quiz_1 with score 80
  2. Claim again for quiz_1 — should panic with "reward already claimed"

test_multiple_quiz_rewards

  1. Claim quiz_1 with score 80 -> 8000 tokens
  2. Claim quiz_2 with score 60 -> 6000 tokens
  3. Assert balance = 14000, total_supply = 14000

test_learner_to_learner_transfer

  1. Claim quiz_1 with score 100 -> 10000 tokens
  2. Transfer 3000 to other_learner
  3. Assert: learner balance = 7000, other_learner balance = 3000

test_total_supply_consistency

  1. learner1 claims q1 with score 80 -> 8000
  2. learner2 claims q2 with score 50 -> 5000
  3. Assert total_supply = 13000

Step 3: Implement credential_flow.rs (6 tests)

test_end_to_end_credential_flow

  1. Enroll, complete modules, submit quizzes (scores 85 and 75, avg=80)
  2. Check eligibility: assert!(progress_client.is_eligible_for_credential(learner, &course_id))
  3. Mint credential: credential_client.mint_credential(learner, &course_id, &80, &uri)
  4. Verify: check learner, course_id, score, revoked fields

test_public_verification

  1. Mint a credential
  2. Call verify_credential from any address (no auth needed for reads)
  3. Assert score is correct

test_multiple_course_credentials

  1. Mint credential for rust_101 and sol_201
  2. get_credentials_for(learner) returns 2 IDs containing both

test_revoked_credential_shows_revoked_status

  1. Mint credential, verify valid
  2. Revoke (admin auth required — use env.mock_all_auths())
  3. Verify revoked: true and is_credential_valid returns false

test_credential_metadata_uri

  1. Mint with ipfs://QmTestMetadata
  2. Verify info.metadata_uri == Symbol::new(env, "ipfs://QmTestMetadata")

test_credential_has_issuance_timestamp

  1. Mint credential
  2. Assert info.issued_at > 0

How to run

cd chainlearn-contracts
cargo test --test token_flow
cargo test --test credential_flow

References

  • All 3 contracts are fully implemented with inline #[cfg(test)] tests that pass
  • Fixtures file: tests/integration/fixtures.rs (89 lines)
  • Token flow: tests/integration/token_flow.rs (115 lines)
  • Credential flow: tests/integration/credential_flow.rs (133 lines)
  • Constants: packages/shared/src/constants.rs

Metadata

Metadata

Assignees

No one assigned

    Labels

    intermediateIntermediate difficultyrustRust 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