Quickstart

Learn how to test a simple counter contract using the Clarinet JS SDK.

In this quickstart guide, you will initialize a simulated development network for testing a smart contract using the Clarinet JS SDK. You'll learn how to initialize your project, interact with a smart contract, call its functions, and test the results.

Check out the methods page for the Clarinet JS SDK to learn about the different ways that you can interact with simnet.


Prerequisites

To follow this quickstart guide, you'll need:

  1. NPM and Node.js 18.0 or later installed on your machine. We recommend Volta to manage your JS tooling.
  2. The Clarinet quickstart project. We will be using the counter contract from that quickstart here.

Importing dependencies

Before we dive in, navigate to your project and import the Cl helper from the @stacks/transactions package in your test file.

counter.clar
counter.test.ts
.gitignore
Clarinet.toml
package.json
tsconfig.json
vitest.config.js
counter.test.ts
import { describe, expect, it } from "vitest";
import { Cl } from "@stacks/transactions";

The Cl namespace simplifies the process of creating and handling Clarity values. This functionality is particularly useful in testing environments where developers need to simulate contract interactions accurately.

Retrieve an account from the simnet

For most test cases, you'll want to retrieve an account from the network in order to interact with your smart contracts. The following code uses the getAccounts method to achieve this.

counter.test.ts
import { describe, expect, it } from "vitest";
import { Cl } from "@stacks/transactions";

const accounts = simnet.getAccounts();
const wallet = accounts.get("wallet_1")!;

Write your first test

The process for writing tests for smart contracts with the Clarinet JS SDK follows a structured approach similar to testing in JavaScript. Here's a breakdown of the steps involved:

  1. Define the group of tests you want to run using the describe block.
  2. Define the test you want to run using the it block.
  3. Call the function and assert the result using the expect function.

Now that you understand the key components for writing tests, start by writing a test that ensures the counter contract has been deployed.

counter.test.ts
describe("counter contract", () => {
  it("ensures the contract is deployed", () => {
    const contractSource = simnet.getContractSource("counter");
    expect(contractSource).toBeDefined();
  });
});

Test the count-up function

Now it's time to call a public function and assert the result. The count-up function is expected to increment the count of the user's principal by 1. Write a test to ensure this behaves as expected.

counter.test.ts
  describe("counter contract", () => {
    it("increments the count of the user's principal by 1", () => {
      const countUpCall = simnet.callPublicFn("counter", "count-up", [], wallet);
      expect(countUpCall.result).toBeOk(Cl.bool(true));
      
      const getCountCall = simnet.callReadOnlyFn(
        "counter",
        "get-count",
        [Cl.principal(wallet)],
        wallet
      );
      expect(getCountCall.result).toBeUint(1);
    });
  });

Above, the count-up function is called, and the result is asserted to return an (ok true). Then, the count for the user's principal is retrieved and asserted to be u1.

Custom matchers

The toBeOk and toBeUint methods are used to ensure the count-up function returns the proper Clarity values. For more details, check out the custom matchers page.

Run your tests

Every generated project comes with a package.json file that contains the necessary dependencies and scripts to run your tests.

package.json
"scripts": {
  "test": "vitest run",
  "test:report": "vitest run -- --coverage --costs",
  "test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\""
}

You can now run your tests, with your preferred package manager, by executing the following command:

npm run test

Next steps