Skip to content

Commit df1f3ac

Browse files
committed
add tests for set attributes
1 parent 48f9376 commit df1f3ac

File tree

2 files changed

+60
-121
lines changed

2 files changed

+60
-121
lines changed

pallets/fruniques/src/lib.rs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub mod pallet {
2121
use frame_support::{pallet_prelude::*, transactional, BoundedVec};
2222
use frame_system::pallet_prelude::*;
2323
use scale_info::prelude::vec::Vec;
24-
use sp_runtime::Permill;
2524
/// Configure the pallet by specifying the parameters and types on which it depends.
2625
#[pallet::config]
2726
pub trait Config: frame_system::Config + pallet_uniques::Config {
@@ -41,22 +40,25 @@ pub mod pallet {
4140
#[pallet::event]
4241
#[pallet::generate_deposit(pub(super) fn deposit_event)]
4342
pub enum Event<T: Config> {
44-
// A frunique and asset class were succesfully created!
43+
// A frunique and asset class were successfully created!
4544
FruniqueCollectionCreated(T::AccountId, T::CollectionId),
46-
// A frunique and asset class were succesfully created!
45+
// A frunique and asset class were successfully created!
4746
FruniqueCreated(T::AccountId, T::AccountId, T::CollectionId, T::ItemId),
48-
// A frunique/unique was succesfully divided!
47+
// A frunique/unique was successfully divided!
4948
FruniqueDivided(T::AccountId, T::AccountId, T::CollectionId, T::ItemId),
5049
// Counter should work?
5150
NextFrunique(u32),
5251
}
5352

5453
#[pallet::error]
5554
pub enum Error<T> {
56-
NoneValue,
55+
// The user does not have permission to perform this action
5756
NoPermission,
57+
// Only the owner of the Frunique can perform this action
5858
NotAdmin,
59+
// The storage is full
5960
StorageOverflow,
61+
// A feature not implemented yet
6062
NotYetImplemented,
6163
// Too many fruniques were minted
6264
FruniqueCntOverflow,
@@ -70,6 +72,10 @@ pub mod pallet {
7072
AttributesEmpty,
7173
// The collection doesn't exist
7274
CollectionNotFound,
75+
// The parent doesn't exist
76+
ParentNotFound,
77+
// The frunique doesn't exist
78+
FruniqueNotFound,
7379
}
7480

7581
#[pallet::storage]
@@ -118,7 +124,7 @@ pub mod pallet {
118124
Blake2_128Concat,
119125
CollectionId, // Parent collection id
120126
Blake2_128Concat,
121-
ItemId, // Parent item id
127+
ItemId, // Parent item id
122128
Option<ChildInfo>, // ParentId and flag if it inherit attributes
123129
ValueQuery,
124130
>;
@@ -152,7 +158,6 @@ pub mod pallet {
152158
Self::account_id_to_lookup_source(&admin),
153159
)?;
154160

155-
156161
Self::deposit_event(Event::FruniqueCollectionCreated(admin, new_collection_id));
157162

158163
<NextCollection<T>>::put(Self::next_collection() + 1);
@@ -178,12 +183,12 @@ pub mod pallet {
178183

179184
/// ## Set multiple attributes to a frunique.
180185
/// `origin` must be signed by the owner of the frunique.
186+
/// - `class_id` must be a valid class of the asset class.
187+
/// - `instance_id` must be a valid instance of the asset class.
181188
/// - `attributes` must be a list of pairs of `key` and `value`.
182189
/// `key` must be a valid key for the asset class.
183190
/// `value` must be a valid value for the asset class.
184191
/// `attributes` must not be empty.
185-
/// - `instance_id` must be a valid instance of the asset class.
186-
/// - `class_id` must be a valid class of the asset class.
187192
188193
#[pallet::weight(10_000 + T::DbWeight::get().writes(1))]
189194
pub fn set_attributes(
@@ -192,6 +197,8 @@ pub mod pallet {
192197
instance_id: T::ItemId,
193198
attributes: Vec<(BoundedVec<u8, T::KeyLimit>, BoundedVec<u8, T::ValueLimit>)>,
194199
) -> DispatchResult {
200+
ensure!(Self::item_exists(&class_id, &instance_id), <Error<T>>::FruniqueNotFound);
201+
195202
// ! Ensure the admin is the one who can add attributes to the frunique.
196203
let admin = Self::admin_of(&class_id, &instance_id);
197204
let signer = core::prelude::v1::Some(ensure_signed(origin.clone())?);
@@ -234,36 +241,20 @@ pub mod pallet {
234241
parent_info: Option<HierarchicalInfo>,
235242
attributes: Option<Vec<(BoundedVec<u8, T::KeyLimit>, BoundedVec<u8, T::ValueLimit>)>>,
236243
) -> DispatchResult {
244+
ensure!(Self::collection_exists(&class_id), <Error<T>>::CollectionNotFound);
237245

238-
ensure!(Self::collection_exists(&class_id), <Error<T>>::CollectionNotFound);
246+
if let Some(parent_info) = parent_info {
247+
ensure!(Self::item_exists(&class_id, &parent_info.0), <Error<T>>::ParentNotFound);
248+
}
239249

240250
let owner: T::AccountId = ensure_signed(origin.clone())?;
241251
let account_id = Self::account_id_to_lookup_source(&owner);
242252

243253
let instance_id: ItemId = <NextFrunique<T>>::try_get(class_id).unwrap_or(0);
244254
<NextFrunique<T>>::insert(class_id, instance_id + 1);
245255

246-
Self::do_spawn(
247-
origin.clone(),
248-
class_id,
249-
instance_id,
250-
account_id,
251-
attributes,
252-
)?;
253-
254-
Self::deposit_event(Event::FruniqueCreated(
255-
owner.clone(),
256-
owner,
257-
class_id,
258-
instance_id,
259-
));
260-
261-
262256
if let Some(parent_info) = parent_info {
263-
ensure!(
264-
Self::item_exists(&class_id, &parent_info.0),
265-
<Error<T>>::CollectionNotFound
266-
);
257+
ensure!(Self::item_exists(&class_id, &parent_info.0), <Error<T>>::ParentNotFound);
267258
<FruniqueParent<T>>::insert(class_id, instance_id, Some(parent_info));
268259

269260
let child_info = ChildInfo {
@@ -274,9 +265,17 @@ pub mod pallet {
274265
};
275266

276267
<FruniqueChild<T>>::insert(class_id, instance_id, Some(child_info));
277-
278268
}
279269

270+
Self::do_spawn(origin.clone(), class_id, instance_id, account_id, attributes)?;
271+
272+
Self::deposit_event(Event::FruniqueCreated(
273+
owner.clone(),
274+
owner,
275+
class_id,
276+
instance_id,
277+
));
278+
280279
Ok(())
281280
}
282281

pallets/fruniques/src/tests.rs

Lines changed: 30 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ use core::convert::TryFrom;
33
use codec::{Encode};
44

55
use frame_support::{assert_noop, assert_ok, BoundedVec};
6-
use sp_runtime::Permill;
76

87
pub struct ExtBuilder;
98

109
// helper function to set BoundedVec
11-
macro_rules! bvec {
12-
($( $x:tt )*) => {
13-
vec![$( $x )*].try_into().unwrap()
14-
}
15-
}
10+
// macro_rules! bvec {
11+
// ($( $x:tt )*) => {
12+
// vec![$( $x )*].try_into().unwrap()
13+
// }
14+
// }
1615

1716
impl Default for ExtBuilder {
1817
fn default() -> Self {
@@ -46,10 +45,11 @@ fn dummy_attributes() -> Vec<(BoundedVec<u8, KeyLimit>, BoundedVec<u8, ValueLimi
4645
)]
4746
}
4847

49-
fn dummy_value() -> Permill {
50-
Permill::from_percent(50)
48+
fn dummy_empty_attributes() -> Vec<(BoundedVec<u8, KeyLimit>, BoundedVec<u8, ValueLimit>)> {
49+
vec![]
5150
}
5251

52+
5353
#[test]
5454
fn create_collection_works() {
5555
ExtBuilder::default().build().execute_with(|| {
@@ -63,98 +63,38 @@ fn spawn_extrinsic_works() {
6363
// A collection must be created before spawning an NFT
6464
assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, None), Error::<Test>::CollectionNotFound);
6565

66+
// Create a collection
6667
assert_ok!(Fruniques::create_collection(Origin::signed(1), Some(dummy_description())));
68+
69+
// The first item can not be a child
70+
assert_noop!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), None), Error::<Test>::ParentNotFound);
71+
6772
// A NFT can be created with empty data
6873
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, None));
6974
// A NFT can be created with attributes
7075
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, Some(dummy_attributes())));
7176
// A NFT can be hierarchical
7277
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), None));
73-
78+
// The parent must exist
79+
assert_noop!(Fruniques::spawn(Origin::signed(1), 0, Some((100, false, 10)), None), Error::<Test>::ParentNotFound);
7480
})
7581
}
7682

77-
// #[test]
78-
// fn create_frunique_works() {
79-
// // Create a frunique
80-
// ExtBuilder::default().build().execute_with(|| {
81-
// assert_ok!(Fruniques::create(Origin::signed(1), 1, 0, Some(Permill::from_percent(50)), 1));
82-
// });
83-
// }
8483

85-
// #[test]
86-
// fn create_frunique_with_attributes_should_work() {
87-
// // Create a frunique with attributes
88-
// ExtBuilder::default().build().execute_with(|| {
89-
// assert_noop!(
90-
// Fruniques::create_with_attributes(
91-
// Origin::signed(1),
92-
// 1,
93-
// 0,
94-
// Some(Permill::from_percent(50)),
95-
// 1,
96-
// vec![]
97-
// ),
98-
// Error::<Test>::AttributesEmpty
99-
// );
100-
101-
// assert_ok!(Fruniques::create_with_attributes(
102-
// Origin::signed(1),
103-
// 1,
104-
// 0,
105-
// Some(Permill::from_percent(50)),
106-
// 1,
107-
// vec![(bvec![0], bvec![0])],
108-
// ));
109-
// });
110-
// }
84+
#[test]
85+
fn set_attributes_works() {
86+
ExtBuilder::default().build().execute_with(|| {
87+
// A collection must be created before spawning an NFT
88+
assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, None), Error::<Test>::CollectionNotFound);
11189

112-
// this test is failing for some reason...
113-
/*---- tests::spawn_extrinsic_works stdout ----
114-
thread 'tests::spawn_extrinsic_works' panicked at 'Expected Ok(_). Got Err(
115-
Module(
116-
ModuleError {
117-
index: 1,
118-
error: [
119-
1,
120-
0,
121-
0,
122-
0,
123-
],
124-
message: Some(
125-
"UnknownCollection",
126-
),
127-
},
128-
),
129-
)', pallets/fruniques/src/tests.rs:41:9
130-
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
131-
*/
132-
// #[test]
133-
// fn spawn_extrinsic_works() {
134-
// ExtBuilder::default().build().execute_with(|| {
135-
// assert_ok!(Fruniques::create(Origin::signed(1), 1, 0, Some(Permill::from_percent(50)), 1));
136-
// assert_ok!(Fruniques::spawn(
137-
// Origin::signed(1),
138-
// 1,
139-
// 255,
140-
// true,
141-
// Permill::from_float(20.525),
142-
// 1
143-
// ));
144-
// //Fruniques::spawn(Origin::signed(1),1,255,true,Permill::from_float(20.525),1 );
145-
// assert_ok!(Fruniques::spawn(Origin::signed(1), 1, 1, true, Permill::from_float(20.525), 1));
146-
// assert_ok!(Fruniques::instance_exists(Origin::signed(1), 1, 1));
147-
// });
148-
// }
90+
// Create a collection
91+
assert_ok!(Fruniques::create_collection(Origin::signed(1), Some(dummy_description())));
92+
// Attributes can be added only to existing NFTs
93+
assert_noop!(Fruniques::set_attributes(Origin::signed(1), 0, 0, dummy_attributes()), Error::<Test>::FruniqueNotFound);
94+
// A NFT can be created with empty data
95+
assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, None));
96+
// Attributes can not be empty
97+
assert_noop!(Fruniques::set_attributes(Origin::signed(1), 0, 0, dummy_empty_attributes()), Error::<Test>::AttributesEmpty);
14998

150-
// #[test]
151-
// fn set_attributes_should_work() {
152-
// ExtBuilder::default().build().execute_with(|| {
153-
// assert_ok!(Fruniques::create(Origin::signed(1), 0, 0, Some(Permill::from_percent(50)), 1));
154-
// assert_noop!(
155-
// Fruniques::set_attributes(Origin::signed(1), 0, 0, vec![]),
156-
// Error::<Test>::AttributesEmpty
157-
// );
158-
// assert_ok!(Fruniques::set_attributes(Origin::signed(1), 0, 0, vec![(bvec![0], bvec![0])]));
159-
// });
160-
// }
99+
})
100+
}

0 commit comments

Comments
 (0)