Description
The file tests/unit/token_tests.rs contains 8 test function skeletons for the learn-token contract. Every test has the correct #[test] / #[should_panic] annotations and Soroban Env setup, but all contract invocations and assertions are commented out. As a result, these tests compile and "pass" without exercising any contract logic.
The goal is to uncomment and wire up these tests so they call the real LearnToken contract and assert real behavior.
How to set up each test
Every test needs to:
- Create a Soroban
Env with Env::default()
- Generate an admin address with
Address::generate(&env)
- Register the contract:
let contract_id = env.register(LearnToken, ());
- Create a client:
let client = LearnTokenClient::new(&env, &contract_id);
- Initialize the token:
client.initialize(&admin, &Symbol::new(&env, "CLearn"), &Symbol::new(&env, "CLRN"), &7);
- Call
env.mock_all_auths(); to bypass auth checks in tests
The inline tests at the bottom of contracts/learn-token/src/lib.rs (lines 239-335) show working examples of this pattern.
Tests to uncomment and complete
test_token_metadata_after_init
What it verifies: After initialization, name(), symbol(), decimals(), and total_supply() return the correct values.
let (admin, contract_id) = setup_token(&env);
let client = LearnTokenClient::new(&env, &contract_id);
assert_eq!(client.name(), Symbol::new(&env, "CLearn"));
assert_eq!(client.symbol(), Symbol::new(&env, "CLRN"));
assert_eq!(client.decimals(), 7);
assert_eq!(client.total_supply(), 0);
assert_eq!(client.admin(), admin);
test_mint_increases_balance_and_supply
What it verifies: mint(&recipient, &1000) increases balance(&recipient) to 1000 and total_supply() to 1000.
client.mint(&recipient, &1000);
assert_eq!(client.balance(&recipient), 1000);
assert_eq!(client.total_supply(), 1000);
test_transfer_moves_tokens
What it verifies: After minting 500 to alice, transfer(&alice, &bob, &200) leaves alice with 300 and bob with 200.
client.mint(&alice, &500);
client.transfer(&alice, &bob, &200);
assert_eq!(client.balance(&alice), 300);
assert_eq!(client.balance(&bob), 200);
test_transfer_insufficient_balance
What it verifies: #[should_panic(expected = "insufficient balance")] — transferring more than balance panics.
client.mint(&alice, &100);
client.transfer(&alice, &bob, &200); // panics
test_claim_reward_proportional_minting
What it verifies: claim_reward(&learner, &quiz_id, &80) returns 80 * 100 = 8000 (BASE_REWARD_PER_POINT = 100 from packages/shared/src/constants.rs:13). Balance and total_supply should also be 8000.
let quiz_id = Symbol::new(&env, "quiz_1");
let reward = client.claim_reward(&learner, &quiz_id, &80);
assert_eq!(reward, 8000);
assert_eq!(client.balance(&learner), 8000);
assert_eq!(client.total_supply(), 8000);
test_claim_reward_double_claim
What it verifies: #[should_panic(expected = "reward already claimed")] — calling claim_reward twice with the same quiz_id panics.
let quiz_id = Symbol::new(&env, "quiz_1");
client.claim_reward(&learner, &quiz_id, &80);
client.claim_reward(&learner, &quiz_id, &80); // panics
test_claim_reward_rejects_high_score
What it verifies: #[should_panic(expected = "score exceeds maximum")] — score > 100 (MAX_QUIZ_SCORE) panics.
let quiz_id = Symbol::new(&env, "quiz_1");
client.claim_reward(&learner, &quiz_id, &101); // panics
test_transfer_from_with_allowance
What it verifies: approve(&owner, &spender, &500, &999999) sets allowance, then transfer_from(&spender, &owner, &recipient, &300) moves 300 and decreases allowance to 200.
client.mint(&owner, &1000);
client.approve(&owner, &spender, &500, &999999);
client.transfer_from(&spender, &owner, &recipient, &300);
assert_eq!(client.balance(&owner), 700);
assert_eq!(client.balance(&recipient), 300);
assert_eq!(client.allowance(&owner, &spender), 200);
Imports needed
use learn_token::{LearnToken, LearnTokenClient};
use soroban_sdk::{symbol_short, testutils::Address as _, Address, Env, Symbol};
How to run
cd chainlearn-contracts
cargo test --package learn-token --test token_tests
References
- Contract source:
contracts/learn-token/src/lib.rs (335 lines)
- Storage layer:
contracts/learn-token/src/storage.rs (120 lines)
- Constants:
packages/shared/src/constants.rs — BASE_REWARD_PER_POINT = 100, MAX_QUIZ_SCORE = 100, TOKEN_DECIMALS = 7
- Working inline test examples:
contracts/learn-token/src/lib.rs:239-335
- Soroban testing docs: https://soroban.stellar.org/docs
Description
The file
tests/unit/token_tests.rscontains 8 test function skeletons for thelearn-tokencontract. Every test has the correct#[test]/#[should_panic]annotations and SorobanEnvsetup, but all contract invocations and assertions are commented out. As a result, these tests compile and "pass" without exercising any contract logic.The goal is to uncomment and wire up these tests so they call the real
LearnTokencontract and assert real behavior.How to set up each test
Every test needs to:
EnvwithEnv::default()Address::generate(&env)let contract_id = env.register(LearnToken, ());let client = LearnTokenClient::new(&env, &contract_id);client.initialize(&admin, &Symbol::new(&env, "CLearn"), &Symbol::new(&env, "CLRN"), &7);env.mock_all_auths();to bypass auth checks in testsThe inline tests at the bottom of
contracts/learn-token/src/lib.rs(lines 239-335) show working examples of this pattern.Tests to uncomment and complete
test_token_metadata_after_initWhat it verifies: After initialization,
name(),symbol(),decimals(), andtotal_supply()return the correct values.test_mint_increases_balance_and_supplyWhat it verifies:
mint(&recipient, &1000)increasesbalance(&recipient)to 1000 andtotal_supply()to 1000.test_transfer_moves_tokensWhat it verifies: After minting 500 to alice,
transfer(&alice, &bob, &200)leaves alice with 300 and bob with 200.test_transfer_insufficient_balanceWhat it verifies:
#[should_panic(expected = "insufficient balance")]— transferring more than balance panics.test_claim_reward_proportional_mintingWhat it verifies:
claim_reward(&learner, &quiz_id, &80)returns80 * 100 = 8000(BASE_REWARD_PER_POINT = 100 frompackages/shared/src/constants.rs:13). Balance and total_supply should also be 8000.test_claim_reward_double_claimWhat it verifies:
#[should_panic(expected = "reward already claimed")]— callingclaim_rewardtwice with the samequiz_idpanics.test_claim_reward_rejects_high_scoreWhat it verifies:
#[should_panic(expected = "score exceeds maximum")]— score > 100 (MAX_QUIZ_SCORE) panics.test_transfer_from_with_allowanceWhat it verifies:
approve(&owner, &spender, &500, &999999)sets allowance, thentransfer_from(&spender, &owner, &recipient, &300)moves 300 and decreases allowance to 200.Imports needed
How to run
References
contracts/learn-token/src/lib.rs(335 lines)contracts/learn-token/src/storage.rs(120 lines)packages/shared/src/constants.rs—BASE_REWARD_PER_POINT = 100,MAX_QUIZ_SCORE = 100,TOKEN_DECIMALS = 7contracts/learn-token/src/lib.rs:239-335