# 7.3 Doko JS testing framework

In this module, we’ll walk through writing and running tests using the DokoJS framework. DokoJS gives a powerful yet intuitive toolkit for writing and running tests for Leo programs. It will generate automatically typescript code for interacting with and testing your program. Here, we'll look looking closely at how contracts are interacted with in TypeScript, how test files are structured, and how to run your tests in different modes. If you’ve used Jest or Mocha before, DokoJS will feel right at home. But since we’re dealing with zero-knowledge proofs, private programs, and encrypted records, we’ll need to handle a few extra things under the hood.

### Intallation

First head to:\
<https://github.com/venture23-aleo/doko-js>

And make sure to follow all the instructions to install latest version of Doko JS.

### Setting Up Doko JS

Initialize a new project by giving the name of the project.

```
dokojs init <PROJECT_NAME>
```

First, make sure your project is initialized and compiled. You should already have this structure (or something like it):

```
my-project/
├── programs/
│   └── token.leo
├── artifacts/
│   ├── js/
│   └── leo/
├── test/
│   └── token.test.ts
├── aleo-config.js
└── ...
```

If you don’t have a `test/` directory yet, create one now. This is where all your `.test.ts` files will live.

You should then update the `aleo-config.js` file with custom key and network environement variable values.

#### Adding or Modifying a Program

To add a new Leo program, simply create a new file inside the `programs/` directory. If you're updating an existing one, you can either modify the file directly or use the CLI command:

```bash
dokojs add [PROGRAM_NAME]
```

This streamlines program setup and ensures consistency across your project.

#### Compilation

Once your programs are in place, compile the project by running:

```bash
dokojs compile
```

This command generates an `artifacts/` folder containing two key directories:

* **leo** – This folder holds the compiled Leo packages. For every `.leo` file inside `programs/`, a corresponding package is created here. DokoJS copies your Leo source code into `src/main.leo`, compiles it, and if successful, produces `.aleo` files and build artifacts.
* **js** – This folder contains everything needed to work with your Leo programs in TypeScript. It includes:
  * Type definitions (`types/`)
  * Type conversion helpers (`js2leo` for converting JS to Leo, `leo2js` for the reverse)
  * Program interfaces (`.ts` files with transitions and mappings)

Each program gets its own fully-typed interface, making it easy to interact with your contracts in tests, scripts, or production code.

Now let’s take a look at a test file.

### Writing Your First DokoJS Test

Here's an example test suite for a simple `token` contract:

```ts
import { ExecutionMode } from '@doko-js/core';
import { TokenContract } from '../artifacts/js/token';
import { decrypttoken } from '../artifacts/js/leo2js/token';
import { PrivateKey } from '@provablehq/sdk';

const TIMEOUT = 200_000;

const mode = ExecutionMode.SnarkExecute;
const contract = new TokenContract({ mode });

const [admin] = contract.getAccounts();
const recipient = process.env.ALEO_DEVNET_PRIVATE_KEY3;

describe('Token Contract', () => {
  test('deploy', async () => {
    const tx = await contract.deploy();
    await tx.wait();
  }, TIMEOUT);

  test('mint public tokens', async () => {
    const amount = BigInt(5000);
    const tx = await contract.mint_public(admin, amount);
    await tx.wait();

    const balance = await contract.account(admin);
    expect(balance).toBe(amount);
  }, TIMEOUT);

  test('mint private tokens', async () => {
    const amount = BigInt(10000);
    const tx = await contract.mint_private(admin, amount);
    const [record] = await tx.wait();

    const decrypted = decrypttoken(record, process.env.ALEO_PRIVATE_KEY_TESTNET3);
    expect(decrypted.amount).toBe(amount);
  }, TIMEOUT);
});
```

Let’s break this down.

#### Anatomy of a Test File

* **Importing the contract**: `TokenContract` is auto-generated during compilation. It gives you typed access to all contract methods.
* **Execution Mode**: You can choose between `SnarkExecute` and `LeoRun`. Use the former to broadcast transactions to the blockchain; use the latter for local dry-runs.
* **Getting Accounts**: `contract.getAccounts()` returns addresses derived from your private keys. This maps to what's in your `aleo-config.js`.
* **Deploying and Interacting**: You deploy using `contract.deploy()`, then call methods like `mint_public` and `mint_private`, and assert outcomes with `expect()`.

Remember: private values (like token amounts) are encrypted. To assert them, you’ll need to decrypt the record using helper functions like `decrypttoken`. automatically generated&#x20;

### Running Your Tests

To run **all** tests in your project, simply run:

```bash
npm run test
```

To run a **specific test file**, pass the filename (or just part of it):

```bash
npm run test -- token
```

This will run any test files matching `token.*.ts`.

Or run it directly with Jest for more control:

```bash
npm test -- --runInBand test/token.test.ts
```

The `--runInBand` flag ensures your tests run sequentially, which helps when dealing with stateful blockchain tests.

### Under the Hood: Where the Magic Happens

When you compile your project (`dokojs compile`), DokoJS generates JS bindings for each Leo program. These files live inside `artifacts/js/` and include:

```
artifacts/
└── js/
    ├── token.ts              <-- Contract methods
    ├── js2leo/token.ts       <-- Type conversion: JS -> Leo
    ├── leo2js/token.ts       <-- Type conversion: Leo -> JS
    └── types/token.ts        <-- TypeScript definitions
```

So when you write:

```ts
import { TokenContract } from '../artifacts/js/token';
```

You're importing a wrapper around your Leo contract that handles all the encoding, decoding, and blockchain interactions for you. Pretty handy.

### Configuration Tips

Everything is wired through `aleo-config.js`. This file defines:

* **Private keys**
* **Network endpoints**
* **Execution modes**
* **Priority fees**

Here’s a quick peek at a minimal config:

```ts
export default {
  accounts: [process.env.ALEO_PRIVATE_KEY],
  mode: 'execute',
  networks: {
    testnet: {
      endpoint: 'http://localhost:3030',
      accounts: [process.env.ALEO_DEVNET_PRIVATE_KEY1],
      priorityFee: 0.01
    }
  },
  defaultNetwork: 'testnet'
};
```

Want to switch to local mode? Just change the `mode` to `'evaluate'`.

### Decrypting Private Records

When using `mint_private` or `transfer_private`, the resulting records are encrypted on-chain. To verify values, use `decrypttoken()` (or your equivalent based on the contract name).

```ts
import { decrypttoken } from '../artifacts/js/leo2js/token';

const decrypted = decrypttoken(record, PRIVATE_KEY);
expect(decrypted.amount).toBe(expectedAmount);
```

The best way to understand how Doko JS works and how it can be useful for you is to try it directly with your own programs : look into the code it automatically generated on compilation, and writing a few tests on your own.
