Skip to content

Commit

Permalink
fix: tests
Browse files Browse the repository at this point in the history
  • Loading branch information
veeso committed Apr 16, 2024
1 parent de58a4a commit 7b5c55a
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 15 deletions.
26 changes: 14 additions & 12 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ mod test {
fn test_should_get_balance_of() {
init_canister();
store_mock_token(1);
assert_eq!(App::balance_of(caller()).unwrap(), Nat::from(2_u64));
assert_eq!(App::balance_of(caller()).unwrap(), Nat::from(1_u64));
assert!(App::balance_of(Principal::management_canister()).is_err());
}

Expand All @@ -483,6 +483,7 @@ mod test {
fn test_should_get_owner_token_identifiers() {
init_canister();
store_mock_token(1);
store_mock_token(2);
assert_eq!(
App::owner_token_identifiers(caller()).unwrap(),
vec![Nat::from(1_u64), Nat::from(2_u64)]
Expand All @@ -494,6 +495,7 @@ mod test {
fn test_should_get_owner_token_metadata() {
init_canister();
store_mock_token(1);
store_mock_token(2);
let metadata = App::owner_token_metadata(caller()).unwrap();
assert_eq!(metadata.len(), 2);
assert_eq!(metadata[0].owner, Some(caller()));
Expand All @@ -515,7 +517,7 @@ mod test {
});

assert_eq!(
App::operator_of(3_u64.into()).unwrap(),
App::operator_of(2_u64.into()).unwrap(),
Some(Principal::management_canister())
);

Expand All @@ -537,7 +539,7 @@ mod test {
});
assert_eq!(
App::operator_token_identifiers(Principal::management_canister()).unwrap(),
vec![Nat::from(3_u64), Nat::from(4_u64)]
vec![Nat::from(2_u64)]
);
assert!(App::operator_of(5_u64.into()).is_err());
}
Expand All @@ -556,11 +558,9 @@ mod test {
token.operator = Some(Principal::management_canister())
});
let metadata = App::operator_token_metadata(Principal::management_canister()).unwrap();
assert_eq!(metadata.len(), 2);
assert_eq!(metadata.len(), 1);
assert_eq!(metadata[0].owner, Some(caller()));
assert_eq!(metadata[0].token_identifier, Nat::from(3_u64));
assert_eq!(metadata[1].owner, Some(caller()));
assert_eq!(metadata[1].token_identifier, Nat::from(4_u64));
assert_eq!(metadata[0].token_identifier, Nat::from(2_u64));

assert!(App::operator_of(5_u64.into()).is_err());
}
Expand All @@ -572,7 +572,9 @@ mod test {
App::supported_interfaces(),
vec![
SupportedInterface::Burn,
SupportedInterface::TransactionHistory
SupportedInterface::TransactionHistory,
SupportedInterface::Mint,
SupportedInterface::Approval,
]
);
}
Expand All @@ -582,7 +584,7 @@ mod test {
init_canister();
store_mock_token(1);
store_mock_token(2);
assert_eq!(App::total_supply(), Nat::from(4_u64));
assert_eq!(App::total_supply(), Nat::from(2_u64));
}

#[tokio::test]
Expand All @@ -598,7 +600,7 @@ mod test {
.await
.is_ok()
);
assert_eq!(App::balance_of(caller()).unwrap(), Nat::from(1_u64));
assert!(App::balance_of(caller()).is_err());
assert_eq!(
App::balance_of(Principal::management_canister()).unwrap(),
Nat::from(1_u64)
Expand All @@ -616,8 +618,8 @@ mod test {
init_canister();
store_mock_token(1);
assert!(App::burn(1_u64.into()).is_ok());
assert_eq!(App::balance_of(caller()).unwrap(), Nat::from(1_u64));

assert!(App::balance_of(caller()).is_err());
assert!(App::burn(1_u64.into()).is_err());
assert!(App::burn(5_u64.into()).is_err());
}

Expand Down
147 changes: 147 additions & 0 deletions src/app/storage/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,150 @@ impl TokensStorage {
Ok(tx_id)
}
}

#[cfg(test)]
mod test {

use crate::app::test_utils::{alice, bob, store_mock_token_with};

use super::*;

use pretty_assertions::assert_eq;

#[test]
fn test_should_mint_token() {
let id = 1_u64;
let recipient = alice();
let properties = vec![("key".to_string(), GenericValue::Int64Content(1))];

let tx_id = TokensStorage::mint(recipient, id.into(), properties).unwrap();
assert_eq!(tx_id, 0u64);

// get token
let token = TokensStorage::get_token(&id.into()).unwrap();
assert_eq!(token.owner, Some(recipient));
}

#[test]
fn test_should_get_total_supply() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
});
store_mock_token_with(2u64, |token| {
token.owner = Some(alice());
});
store_mock_token_with(3u64, |token| {
token.owner = Some(bob());
});

assert_eq!(TokensStorage::total_supply(), 3);
}

#[test]
fn test_should_get_unique_holders() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
});
store_mock_token_with(2u64, |token| {
token.owner = Some(alice());
});
store_mock_token_with(3u64, |token| {
token.owner = Some(bob());
});

assert_eq!(TokensStorage::total_unique_holders(), 2);
}

#[test]
fn test_should_get_tokens_by_owner() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
});
store_mock_token_with(2u64, |token| {
token.owner = Some(bob());
});
store_mock_token_with(3u64, |token| {
token.owner = Some(alice());
});

assert_eq!(
TokensStorage::tokens_by_owner(alice()),
vec![TokenIdentifier::from(1_u64), TokenIdentifier::from(3_u64)]
);
}

#[test]
fn test_should_get_tokens_by_operator() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
token.operator = Some(bob());
});
store_mock_token_with(2u64, |token| {
token.owner = Some(bob());
});
store_mock_token_with(3u64, |token| {
token.owner = Some(alice());
});

assert_eq!(
TokensStorage::tokens_by_operator(bob()),
vec![TokenIdentifier::from(1_u64)]
);
}

#[test]
fn test_should_set_token_property() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
});
assert!(TokensStorage::set_token_property(
&1_u64.into(),
"key".to_string(),
GenericValue::FloatContent(2.2)
)
.is_ok());
let token = TokensStorage::get_token(&1_u64.into()).unwrap();
assert_eq!(
token.properties,
vec![("key".to_string(), GenericValue::FloatContent(2.2))]
);
}

#[test]
fn test_should_burn_token() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
});
assert!(
TokensStorage::burn(&1u64.into()).is_ok(),
"Should burn token"
);
assert!(
TokensStorage::burn(&1u64.into()).is_err(),
"Should already be burned"
);
}

#[test]
fn test_should_transfer_token() {
store_mock_token_with(1_u64, |token| {
token.owner = Some(alice());
});
assert!(
TokensStorage::transfer(&1u64.into(), bob()).is_ok(),
"Should transfer token"
);
let token = TokensStorage::get_token(&1u64.into()).unwrap();
assert_eq!(token.owner, Some(bob()));
assert!(token.transferred_at.is_some());
assert!(token.transferred_by.is_some());
assert!(
TokensStorage::burn(&1u64.into()).is_ok(),
"Should already be burned"
);
assert!(
TokensStorage::transfer(&1u64.into(), alice()).is_err(),
"Should not allow transfer of burned token"
);
}
}
8 changes: 8 additions & 0 deletions src/app/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,11 @@ where

TokensStorage::get_token(&id.into()).unwrap()
}

pub fn alice() -> Principal {
Principal::from_text("be2us-64aaa-aaaaa-qaabq-cai").unwrap()
}

pub fn bob() -> Principal {
Principal::from_text("bs5l3-6b3zu-dpqyj-p2x4a-jyg4k-goneb-afof2-y5d62-skt67-3756q-dqe").unwrap()
}
115 changes: 115 additions & 0 deletions src/declarations/dip721-canister/dip721-canister.did
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
type CanisterInitData = record {
logo : text;
name : text;
custodians : vec principal;
symbol : text;
supported_interfaces : vec SupportedInterface;
};
type GenericValue = variant {
Nat64Content : nat64;
Nat32Content : nat32;
BoolContent : bool;
Nat8Content : nat8;
Int64Content : int64;
IntContent : int;
NatContent : nat;
Nat16Content : nat16;
Int32Content : int32;
Int8Content : int8;
FloatContent : float64;
Int16Content : int16;
BlobContent : blob;
NestedContent : vec record { text; GenericValue };
Principal : principal;
TextContent : text;
};
type Metadata = record {
logo : opt text;
name : opt text;
created_at : nat64;
upgraded_at : nat64;
custodians : vec principal;
symbol : opt text;
};
type NftError = variant {
UnauthorizedOperator;
SelfTransfer;
TokenNotFound;
UnauthorizedOwner;
TxNotFound;
SelfApprove;
OperatorNotFound;
ExistedNFT;
OwnerNotFound;
Other : text;
};
type Result = variant { Ok : nat; Err : NftError };
type Result_1 = variant { Ok : bool; Err : NftError };
type Result_2 = variant { Ok : opt principal; Err : NftError };
type Result_3 = variant { Ok : vec nat; Err : NftError };
type Result_4 = variant { Ok : vec TokenMetadata; Err : NftError };
type Result_5 = variant { Ok; Err : NftError };
type Result_6 = variant { Ok : TokenMetadata; Err : NftError };
type Result_7 = variant { Ok : TxEvent; Err : NftError };
type Stats = record {
cycles : nat;
total_transactions : nat;
total_unique_holders : nat;
total_supply : nat;
};
type SupportedInterface = variant { Burn; Mint; Approval; TransactionHistory };
type TokenMetadata = record {
transferred_at : opt nat64;
transferred_by : opt principal;
owner : opt principal;
operator : opt principal;
approved_at : opt nat64;
approved_by : opt principal;
properties : vec record { text; GenericValue };
is_burned : bool;
token_identifier : nat;
burned_at : opt nat64;
burned_by : opt principal;
minted_at : nat64;
minted_by : principal;
};
type TxEvent = record {
time : nat64;
operation : text;
details : vec record { text; GenericValue };
caller : principal;
};
service : (CanisterInitData) -> {
approve : (principal, nat) -> (Result);
balance_of : (principal) -> (Result) query;
burn : (nat) -> (Result);
custodians : () -> (vec principal) query;
cycles : () -> (nat) query;
is_approved_for_all : (principal, principal) -> (Result_1);
logo : () -> (opt text) query;
metadata : () -> (Metadata) query;
mint : (principal, nat, vec record { text; GenericValue }) -> (Result);
name : () -> (opt text) query;
operator_of : (nat) -> (Result_2) query;
operator_token_identifiers : (principal) -> (Result_3) query;
operator_token_metadata : (principal) -> (Result_4) query;
owner_of : (nat) -> (Result_2) query;
owner_token_identifiers : (principal) -> (Result_3) query;
owner_token_metadata : (principal) -> (Result_4) query;
set_approval_for_all : (principal, bool) -> (Result);
set_custodians : (vec principal) -> ();
set_logo : (text) -> ();
set_name : (text) -> ();
set_symbol : (text) -> ();
set_token_property : (nat, text, GenericValue) -> (Result_5);
stats : () -> (Stats) query;
supported_interfaces : () -> (vec SupportedInterface) query;
symbol : () -> (opt text) query;
token_metadata : (nat) -> (Result_6) query;
total_supply : () -> (nat) query;
total_transactions : () -> (nat) query;
total_unique_holders : () -> (nat) query;
transaction : (nat) -> (Result_7) query;
transfer : (principal, nat) -> (Result);
transfer_from : (principal, principal, nat) -> (Result);
}
2 changes: 1 addition & 1 deletion src/declarations/dip721-canister/dip721-canister.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ export interface _SERVICE {
'transfer_from' : ActorMethod<[Principal, Principal, bigint], Result>,
}
export declare const idlFactory: IDL.InterfaceFactory;
export declare const init: ({ IDL }: { IDL: IDL }) => IDL.Type[];
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];
3 changes: 1 addition & 2 deletions src/declarations/dip721-canister/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ export { idlFactory } from "./dip721-canister.did.js";
* beginning in dfx 0.15.0
*/
export const canisterId =
process.env.CANISTER_ID_DIP721-CANISTER ||
process.env.DIP721-CANISTER_CANISTER_ID;
process.env.CANISTER_ID_DIP721-CANISTER;

export const createActor = (canisterId, options = {}) => {
const agent = options.agent || new HttpAgent({ ...options.agentOptions });
Expand Down

0 comments on commit 7b5c55a

Please sign in to comment.