Test

Continuing on from where we left off in the last test we will now read and increment the counter.

Continue adding to the bottom of the same test.

`tests/counter.rs` code from previous section.
#![allow(unused)]
fn main() {
use essential_app_utils::{compile::compile_pint_project, local_server::setup_server};
use counter_app::App;
use essential_types::{PredicateAddress, Word};

#[tokio::test]
async fn test_counter() {
    let (addr, _server) = setup_server().await.unwrap();

    let counter = compile_pint_project(
        concat!(env!("CARGO_MANIFEST_DIR"), "/../contract").into(),
    )
    .await
    .unwrap();

    let contract_address = essential_hash::contract_addr::from_contract(&counter);
    let predicate_address = essential_hash::content_addr(&counter.predicates[0]);
    let predicate_address = PredicateAddress {
        contract: contract_address,
        predicate: predicate_address,
    };

    let mut wallet = essential_wallet::Wallet::temp().unwrap();
    wallet
        .new_key_pair("alice", essential_wallet::Scheme::Secp256k1)
        .unwrap();

    essential_deploy_contract::sign_and_deploy(addr.clone(), "alice", &mut wallet, counter)
        .await
        .unwrap();

    // Add new code here.

}
}

Create a new App we defined earlier in the lib.rs.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    let app = App::new(addr, predicate_address).unwrap();
}
}

Read the current count value and assert that it's 0.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    assert_eq!(app.read_count().await.unwrap(), 0);
}
}

Increment the counter. Remember this creates and submits the solution.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    app.increment().await.unwrap();
}
}

Stepping out of the test function for a second. We want to check for new state however the state only changes once a solution has been included in a block.
Add this wait_for_change function that will check if the state is the expected value. If it is not then it will wait one second and check again.

#![allow(unused)]
fn main() {
async fn wait_for_change(app: &App, expected: Word) {
    loop {
        if app.read_count().await.unwrap() == expected {
            break;
        }
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    }
}
}

Back in the test function now let's use the wait_for_change we just wrote to wait for the count to reach 1.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    wait_for_change(&app, 1).await;
}
}

Exciting the your solution has successfully satisfied the constraints and the state has been mutated.

Now just to make sure let's increment it again.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    app.increment().await.unwrap();
}
}

And wait for the state to change.

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_counter() {
    // ...

    wait_for_change(&app, 2).await;
}
}

The state has changed again to 2!

Check your `tests/counter.rs` matches this.
#![allow(unused)]
fn main() {
use essential_app_utils::{compile::compile_pint_project, local_server::setup_server};
use counter_app::App;
use essential_types::{PredicateAddress, Word};

#[tokio::test]
async fn test_counter() {
    let (addr, _server) = setup_server().await.unwrap();

    let counter = compile_pint_project(
        concat!(env!("CARGO_MANIFEST_DIR"), "/../contract").into(),
    )
    .await
    .unwrap();

    let contract_address = essential_hash::contract_addr::from_contract(&counter);
    let predicate_address = essential_hash::content_addr(&counter.predicates[0]);
    let predicate_address = PredicateAddress {
        contract: contract_address,
        predicate: predicate_address,
    };

    let mut wallet = essential_wallet::Wallet::temp().unwrap();
    wallet
        .new_key_pair("alice", essential_wallet::Scheme::Secp256k1)
        .unwrap();

    essential_deploy_contract::sign_and_deploy(addr.clone(), "alice", &mut wallet, counter)
        .await
        .unwrap();

    let app = App::new(addr, predicate_address).unwrap();

    assert_eq!(app.read_count().await.unwrap(), 0);

    app.increment().await.unwrap();

    wait_for_change(&app, 1).await;
    
    app.increment().await.unwrap();

    wait_for_change(&app, 2).await;
}

async fn wait_for_change(app: &App, expected: Word) {
    loop {
        if app.read_count().await.unwrap() == expected {
            break;
        }
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    }
}
}

Run the test

Run the test and check it all works.

cargo test

Congratulations on building your first essential application.
It may be a very simple example but this declarative way of creating applications is very powerful. \

In future sections we will dive into more complex and interesting applications.

This concludes the "hello world" introduction to the essential system.