Perform basic operations
In this section, we'll explore basic operations on the Chromia blockchain. We'll focus on adding data to the blockchain through transactions. By the end of this tutorial, you will understand how to create users, make posts, and manage followers within your dapp.
Add data through transactions
In Chromia, data is added to the blockchain by sending transactions, each of which can contain one or more database operations known as "operations." Let's start by defining the operations for creating users, making posts, and following users.
Create a user
operation create_user(name, pubkey) {
create user(name, pubkey);
}
The create_user
operation creates a new user. It takes two parameters: name
(user's name) and pubkey
(public key).
Then, it inserts data into the user
entity using the create
keyword.
We use a public key as id
, and thanks to Rell's ability to identify types, we can pass these directly to the
constructor without specifying the fields explicitly.
pubkey
is abyte_array
with a length of 32 or 64, which is common for public keys.
An alternate, more explicit notation would be:
create user( name = name, id = pubkey );
Make a post
operation make_post(user_id: byte_array, content: text) {
create post(
user @ { user_id },
content
);
}
The make_post
operation allows users to create posts. It requires the user_id
(of the user making the post) and the
content
(text content of the post). Note that we don't need to specify the timestamp because we've set a default value
in the entity definition.
Follow a user
operation follow_user(user_id: byte_array, follow_id: byte_array) {
val user = user @ { user_id };
val follow = user @ { follow_id };
create follower(
user = follow,
follower = user
);
}
The follow_user
operation enables one user to follow another user. It requires two parameters: user_id
(ID of the
user who wants to follow) and follow_id
(ID of the user to be followed). We explicitly query the database for both
users and then create a follower
entity to establish the relationship.
Unfollow a user
To unfollow a user, we want to do the opposite of following. We must, therefore, delete the follower
entity
operation unfollow_user(user_id: byte_array, unfollow_id: byte_array) {
val user = user @ { user_id };
val unfollow = user @ { unfollow_id };
delete follower @? { .user == unfollow, .follower == user };
}
Test the operations
Let's add unit tests to ensure your dapp code works as intended. Testing is crucial to the development to verify that your operations produce the expected results.
Set up the test module
-
In your project's directory, navigate to the test folder. If the test folder doesn't exist, create one.
-
Inside the test folder, create a new file named
my_news_feed_test.rell
. This file will contain your test cases. -
Add the following header to
my_news_feed_test.rell
:
@test module;
import main.*;
- The
@test
module declaration indicates that this module contains test code. - The
import main.*;
line imports everything from themain
module, making your dapp code accessible for testing.
Write test cases
Let's write some test cases to ensure your dapp functions correctly. We'll test the creation of users, following relationships, and posts.
@test module;
import main.*;
val alice = rell.test.pubkeys.alice;
val bob = rell.test.pubkeys.bob;
function test_create_entities() {
// Test the creation of two users: Alice and Bob
rell.test.tx()
.op(create_user("Alice", alice))
.op(create_user("Bob", bob))
.run();
// Check if there are two users in the user table
assert_equals(user @ { } (@sum 1), 2);
// Alice follows Bob and makes a post
rell.test.tx()
.op(follow_user(alice, bob))
.op(make_post(alice, "My post"))
.run();
// Check if there is one follower and one post
assert_equals(follower @ { } (@sum 1), 1);
assert_equals(post @ { } (@sum 1), 1);
// Alice unfollows Bob and no followers should now exist
rell.test.tx()
.op(unfollow_user(alice, bob))
.run();
assert_equals(follower @ { } (@sum 1), 0);
}
In this test case:
- We use two public keys,
alice
andbob
from the Rell test framework as user IDs. - The function
test_create_entities
is prefixed withtest_
to indicate it is a test case and runs a series of transactions to create users, establish a following relationship, and create a post. - After each transaction, we use
assert_equals
to check if the expected number of entities is in the corresponding tables. The@sum
is used to aggregate a value from the table. We use1
as aggregate since we just want the number of entities.
Run the tests
Now that you have written your test, you can run it to verify the functionality of your dapp.
-
Open a terminal and navigate to your project's root directory.
-
Run the following command to execute the tests:
chr test
This command will run the tests located in the test: modules
in the chromia.yml
. If all tests pass, you'll see a
confirmation that your dapp's functionality is working as expected.
Congratulations! You've successfully added unit tests to your dapp, helping ensure its reliability and functionality.
In the next part of this tutorial, we'll explore more advanced topics, including handling user input and security considerations in Chromia blockchain development.