End-to-end integration tests for the Delegation Toolkit. It uses local chain, bundler and paymaster made available via Pimlico's local testing docker compose.
- Docker must be installed and configured in order to run the chain, bundler and paymaster.
- Dependencies must be installed with
yarn installat the root of the monorepo. - Internal packages must be built with
yarn buildat the root of the monorepo.
-
In order to start the infrastructure, and deploy the DeleGator environment, execute the
yarn setupcommand. This will usedocker composeto start the various services, and executescripts/setup-environment.tsto wait for the services to be available, and deploy the Delegator Framework. The environment JSON is written to disk at.gator-env.json. -
Execute the tests with
yarn testwhich will usevitesttest runner to execute the tests. -
The infrastructure can be stopped with
yarn teardownwhich usesdocker composeto stop the various services.
When developing end-to-end tests, you can run step 2 repeatedly without having to start and stop the services in between.
The end-to-end test suite runs the complete test suite including all test cases using yarn test:e2e.
Tests can be added simply by creating a file test/<your-test>.test.ts.
Some guidelines for creating tests:
- Important: tests share a single blockchain instance so should always use generated keys, addresses and salts to avoid conflicts with other tests.
- Each test file should be focussed on a single user story.
- Within a test, any setup required should be executed in
beforeEachhook at the start of the file. - Before the tests themselves, a block comment should outline the user story.
- A number of tests can be included to validate various failure modes or alternatives. These should be kept as concise and simple as possible.
- Common assertions should be centralised into
test/utils/assertions.tsand shared across tests. - All assertions should have descriptive messages.
- Assertions throughout the test can be made to ensure that state is as expected - this can be helpful when debugging failing tests.
When creating a test file, follow this structure:
import { beforeEach, expect, test } from 'vitest';
import { /* your imports */ } from './utils/helpers';
import { /* your imports */ } from './utils/assertions';
// Test setup variables
let smartAccount: MetaMaskSmartAccount<Implementation.Hybrid>;
beforeEach(async () => {
...
});
/*
User story description:
- What is being tested
- Expected behavior
- Any important context
*/
test('Description of the main functionality', async () => {
...
});
test('Description of edge case or alternative scenario', async () => {
...
});
test('Description of failure case', async () => {
...
});Key points about test structure:
-
Test Organization:
- Use
beforeEachfor common setup - Group related assertions together
- Use descriptive test names that explain the scenario
- Include a block comment describing the user story
- Use
-
Common Patterns:
- Use helper functions from
utils/helpers.tsfor common operations - Use assertion functions from
utils/assertions.tsfor consistent validation - Generate unique addresses and keys for each test
- Clean up state in
beforeEachto ensure test isolation runTest_expectSuccessandrunTest_expectFailureto abstract common functionality out of each test within the file
- Use helper functions from