Skip to content

Commit

Permalink
✅ Add integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bal7hazar committed Oct 16, 2024
1 parent 29c5aae commit 06c1cf1
Show file tree
Hide file tree
Showing 17 changed files with 700 additions and 141 deletions.
52 changes: 21 additions & 31 deletions contracts/src/systems/actions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,25 @@ trait IActions<TContractState> {
fn blacklist_game(self: @TContractState, world: felt252, namespace: felt252);
fn remove_game(self: @TContractState, world: felt252, namespace: felt252);
fn register_achievement(
self: @TContractState,
world: felt252,
namespace: felt252,
achievement_id: felt252,
points: u16
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252, points: u16
);
fn update_achievement(
self: @TContractState,
world: felt252,
namespace: felt252,
achievement_id: felt252,
points: u16
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252, points: u16
);
fn publish_achievement(
self: @TContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252
);
fn hide_achievement(
self: @TContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252
);
fn whitelist_achievement(
self: @TContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252
);
fn blacklist_achievement(
self: @TContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252
);
fn remove_achievement(
self: @TContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @TContractState, world: felt252, namespace: felt252, identifier: felt252
);
}

Expand Down Expand Up @@ -190,75 +182,73 @@ mod Actions {
self: @ContractState,
world: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
points: u16,
) {
// [Check] Caller is the game owner
self.controllable.assert_is_game_owner(world, namespace);
// [Effect] Register achievement
self
.registrable
.register_achievement(self.world(), world, namespace, achievement_id, points)
.register_achievement(self.world(), world, namespace, identifier, points)
}

fn update_achievement(
self: @ContractState,
world: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
points: u16,
) {
// [Check] Caller is the game owner
self.controllable.assert_is_game_owner(world, namespace);
// [Effect] Update achievement
self
.registrable
.update_achievement(self.world(), world, namespace, achievement_id, points)
self.registrable.update_achievement(self.world(), world, namespace, identifier, points)
}

fn publish_achievement(
self: @ContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @ContractState, world: felt252, namespace: felt252, identifier: felt252
) {
// [Check] Caller is the game owner
self.controllable.assert_is_game_owner(world, namespace);
// [Effect] Publish achievement
self.registrable.publish_achievement(self.world(), world, namespace, achievement_id);
self.registrable.publish_achievement(self.world(), world, namespace, identifier);
}

fn hide_achievement(
self: @ContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @ContractState, world: felt252, namespace: felt252, identifier: felt252
) {
// [Check] Caller is the game owner
self.controllable.assert_is_game_owner(world, namespace);
// [Effect] Whitelist achievement
self.registrable.whitelist_achievement(self.world(), world, namespace, achievement_id);
self.registrable.whitelist_achievement(self.world(), world, namespace, identifier);
}

fn whitelist_achievement(
self: @ContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @ContractState, world: felt252, namespace: felt252, identifier: felt252
) {
// [Check] Caller is a resource owner or writer
self.controllable.assert_is_authorized();
// [Effect] Whitelist achievement
self.registrable.whitelist_achievement(self.world(), world, namespace, achievement_id);
self.registrable.whitelist_achievement(self.world(), world, namespace, identifier);
}

fn blacklist_achievement(
self: @ContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @ContractState, world: felt252, namespace: felt252, identifier: felt252
) {
// [Check] Caller is a resource owner or writer
self.controllable.assert_is_authorized();
// [Effect] Blacklist achievement
self.registrable.blacklist_achievement(self.world(), world, namespace, achievement_id);
self.registrable.blacklist_achievement(self.world(), world, namespace, identifier);
}

fn remove_achievement(
self: @ContractState, world: felt252, namespace: felt252, achievement_id: felt252
self: @ContractState, world: felt252, namespace: felt252, identifier: felt252
) {
// [Check] Caller is the game owner
self.controllable.assert_is_game_owner(world, namespace);
// [Effect] Remove achievement
self.registrable.remove_achievement(self.world(), world, namespace, achievement_id);
self.registrable.remove_achievement(self.world(), world, namespace, identifier);
}
}
}
13 changes: 5 additions & 8 deletions packages/src/components/achievable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -39,31 +39,28 @@ mod AchievableComponent {
fn create(
self: @ComponentState<TContractState>,
world: IWorldDispatcher,
achievement_id: felt252,
identifier: felt252,
points: u16,
total: u32,
title: ByteArray,
description: ByteArray,
image_uri: ByteArray,
) {
// [Setup] Store
let contract_address = get_contract_address();
let store: Store = StoreTrait::new(world);

// [Event] Emit achievement creation
let contract_address = get_contract_address();
let contract = IContractDispatcher { contract_address };
let namespace = contract.namespace_hash();
let time: u64 = get_block_timestamp();
store
.create(
namespace, achievement_id, points, total, title, description, image_uri, time
);
store.create(namespace, identifier, points, total, title, description, image_uri, time);
}

fn update(
self: @ComponentState<TContractState>,
world: IWorldDispatcher,
achievement_id: felt252,
identifier: felt252,
player_id: felt252,
count: u32,
total: u32,
Expand All @@ -75,7 +72,7 @@ mod AchievableComponent {
let contract_address = get_contract_address();
let namespace = IContractDispatcher { contract_address }.namespace_hash();
let time: u64 = get_block_timestamp();
store.update(namespace, achievement_id, player_id, count, total, time);
store.update(namespace, identifier, player_id, count, total, time);
}
}
}
16 changes: 9 additions & 7 deletions packages/src/components/controllable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod ControllableComponent {

// Starknet imports

use starknet::info::{get_tx_info};
use starknet::info::{get_caller_address};

// Dojo imports

Expand Down Expand Up @@ -42,24 +42,26 @@ mod ControllableComponent {
+IWorldProvider<TContractState>,
+IContract<TContractState>
> of InternalTrait<TContractState> {
fn assert_is_authorized(self: @ComponentState<TContractState>) {
let world = self.get_contract().world();
fn assert_is_authorized(self: @ComponentState<TContractState>, world: IWorldDispatcher) {
let namespace = self.get_contract().namespace_hash();
let caller = get_tx_info().unbox().account_contract_address;
let caller = get_caller_address();
let is_owner = world.is_owner(namespace, caller);
let is_writer = world.is_writer(namespace, caller);
assert(is_owner || is_writer, errors::CONTROLLABLE_UNAUTHORIZED_CALLER);
}

fn assert_is_game_owner(
self: @ComponentState<TContractState>, world: felt252, namespace: felt252
self: @ComponentState<TContractState>,
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252
) {
// [Setup] Datastore
let store: Store = StoreTrait::new(self.get_contract().world());

// [Return] Game owner
let game = store.get_game(world, namespace);
let caller = get_tx_info().unbox().account_contract_address;
let game = store.get_game(world_address, namespace);
let caller = get_caller_address();
assert(game.owner == caller.into(), errors::CONTROLLABLE_UNAUTHORIZED_CALLER);
}
}
Expand Down
32 changes: 15 additions & 17 deletions packages/src/components/registrable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
points: u16,
) {
// [Setup] Datastore
Expand All @@ -192,13 +192,11 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement does not exist
let achievement = store.get_achievement(world_address, namespace, achievement_id);
let achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_not_exist();

// [Effect] Create achievement
let achievement = AchievementTrait::new(
world_address, namespace, achievement_id, points
);
let achievement = AchievementTrait::new(world_address, namespace, identifier, points);

// [Effect] Add achievement to game
game.add(achievement.points);
Expand All @@ -213,7 +211,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
points: u16,
) {
// [Setup] Datastore
Expand All @@ -224,7 +222,7 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement exists
let mut achievement = store.get_achievement(world_address, namespace, achievement_id);
let mut achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_exist();

// [Effect] Update achievement and game
Expand All @@ -242,7 +240,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
) {
// [Setup] Datastore
let store: Store = StoreTrait::new(world);
Expand All @@ -252,7 +250,7 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement exists
let mut achievement = store.get_achievement(world_address, namespace, achievement_id);
let mut achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_exist();

// [Effect] Publish achievement
Expand All @@ -267,7 +265,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
) {
// [Setup] Datastore
let store: Store = StoreTrait::new(world);
Expand All @@ -277,7 +275,7 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement exists
let mut achievement = store.get_achievement(world_address, namespace, achievement_id);
let mut achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_exist();

// [Effect] Hide achievement
Expand All @@ -292,7 +290,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
) {
// [Setup] Datastore
let store: Store = StoreTrait::new(world);
Expand All @@ -302,7 +300,7 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement exists
let mut achievement = store.get_achievement(world_address, namespace, achievement_id);
let mut achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_exist();

// [Effect] Whitelist achievement
Expand All @@ -317,7 +315,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
) {
// [Setup] Datastore
let store: Store = StoreTrait::new(world);
Expand All @@ -327,7 +325,7 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement exists
let mut achievement = store.get_achievement(world_address, namespace, achievement_id);
let mut achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_exist();

// [Effect] Blacklist achievement
Expand All @@ -342,7 +340,7 @@ mod RegistrableComponent {
world: IWorldDispatcher,
world_address: felt252,
namespace: felt252,
achievement_id: felt252,
identifier: felt252,
) {
// [Setup] Datastore
let store: Store = StoreTrait::new(world);
Expand All @@ -352,7 +350,7 @@ mod RegistrableComponent {
game.assert_does_exist();

// [Check] Achievement exists
let mut achievement = store.get_achievement(world_address, namespace, achievement_id);
let mut achievement = store.get_achievement(world_address, namespace, identifier);
achievement.assert_does_exist();

// [Effect] Remove achievement
Expand Down
17 changes: 11 additions & 6 deletions packages/src/events/completion.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use quest::constants;
pub mod errors {
pub const ACHIEVEMENT_INVALID_WORLD: felt252 = 'Achievement: invalid world';
pub const ACHIEVEMENT_INVALID_NAMESPACE: felt252 = 'Achievement: invalid namespace';
pub const ACHIEVEMENT_INVALID_ACHIEVEMENT: felt252 = 'Achievement: invalid id';
pub const ACHIEVEMENT_INVALID_ACHIEVEMENT: felt252 = 'Achievement: invalid identifier';
pub const ACHIEVEMENT_INVALID_PROGRESS: felt252 = 'Achievement: invalid progress';
}

Expand All @@ -18,14 +18,19 @@ pub mod errors {
impl AchievementCompletionImpl of AchievementCompletionTrait {
#[inline]
fn new(
namespace: felt252, id: felt252, player_id: felt252, count: u32, total: u32, time: u64,
namespace: felt252,
identifier: felt252,
player_id: felt252,
count: u32,
total: u32,
time: u64,
) -> AchievementCompletion {
// [Check] Inputs
AchievementCompletionAssert::assert_valid_namespace(namespace);
AchievementCompletionAssert::assert_valid_id(id);
AchievementCompletionAssert::assert_valid_identifier(identifier);
AchievementCompletionAssert::assert_valid_progress(count, total);
// [Return] Achievement
AchievementCompletion { namespace, id, player_id, count, total, time }
AchievementCompletion { namespace, identifier, player_id, count, total, time }
}
}

Expand All @@ -37,8 +42,8 @@ impl AchievementCompletionAssert of AssertTrait {
}

#[inline]
fn assert_valid_id(achivement_id: felt252) {
assert(achivement_id != 0, errors::ACHIEVEMENT_INVALID_ACHIEVEMENT);
fn assert_valid_identifier(identifier: felt252) {
assert(identifier != 0, errors::ACHIEVEMENT_INVALID_ACHIEVEMENT);
}

#[inline]
Expand Down
Loading

0 comments on commit 06c1cf1

Please sign in to comment.