5.6 KiB
5.6 KiB
Testing HyperIndex Indexers
Unit test handlers with MockDb and simulated events.
Setup
- Install test framework:
pnpm i mocha @types/mocha
-
Create test folder and file:
test/test.ts -
Add to
package.json:
"test": "mocha"
- Generate test helpers:
pnpm codegen
Basic Test Structure
import assert from "assert";
import { TestHelpers, UserEntity } from "generated";
const { MockDb, Greeter, Addresses } = TestHelpers;
describe("Greeter Indexer", () => {
it("NewGreeting creates User entity", async () => {
// 1. Create mock database
const mockDb = MockDb.createMockDb();
// 2. Create mock event
const mockEvent = Greeter.NewGreeting.createMockEvent({
greeting: "Hello",
user: Addresses.defaultAddress,
});
// 3. Process event
const updatedDb = await mockDb.processEvents([mockEvent]);
// 4. Assert result
const user = updatedDb.entities.User.get(Addresses.defaultAddress);
assert.equal(user?.latestGreeting, "Hello");
});
});
MockDb API
Create Empty Database
const mockDb = MockDb.createMockDb();
Add Entities
const mockDb = MockDb.createMockDb();
const dbWithEntity = mockDb.entities.User.set({
id: "user-1",
balance: BigInt(1000),
name: "Alice",
});
Get Entities
const user = updatedDb.entities.User.get("user-1");
Process Events
const updatedDb = await mockDb.processEvents([event1, event2, event3]);
Creating Mock Events
Basic Event
const mockEvent = MyContract.Transfer.createMockEvent({
from: "0x123...",
to: "0x456...",
value: BigInt(1000),
});
With Custom Metadata
const mockEvent = MyContract.Transfer.createMockEvent(
{
from: "0x123...",
to: "0x456...",
value: BigInt(1000),
},
{
chainId: 1,
srcAddress: "0xContractAddress",
logIndex: 0,
block: {
number: 12345678,
timestamp: 1699000000,
hash: "0xblockhash...",
},
transaction: {
hash: "0xtxhash...",
},
}
);
Test Patterns
Entity Creation
it("creates entity on event", async () => {
const mockDb = MockDb.createMockDb();
const event = MyContract.Created.createMockEvent({
id: "token-1",
name: "Token",
});
const updatedDb = await mockDb.processEvents([event]);
const token = updatedDb.entities.Token.get("token-1");
assert.ok(token, "Token should exist");
assert.equal(token.name, "Token");
});
Entity Updates
it("updates entity on subsequent events", async () => {
const mockDb = MockDb.createMockDb();
const userAddress = Addresses.defaultAddress;
// First event
const event1 = Greeter.NewGreeting.createMockEvent({
greeting: "Hello",
user: userAddress,
});
// Second event
const event2 = Greeter.NewGreeting.createMockEvent({
greeting: "Hi again",
user: userAddress,
});
const updatedDb = await mockDb.processEvents([event1, event2]);
const user = updatedDb.entities.User.get(userAddress);
assert.equal(user?.numberOfGreetings, 2);
assert.equal(user?.latestGreeting, "Hi again");
});
Pre-existing Entities
it("updates existing entity", async () => {
// Start with entity in database
const mockDb = MockDb.createMockDb()
.entities.Token.set({
id: "token-1",
totalSupply: BigInt(1000),
});
const event = MyContract.Mint.createMockEvent({
tokenId: "token-1",
amount: BigInt(500),
});
const updatedDb = await mockDb.processEvents([event]);
const token = updatedDb.entities.Token.get("token-1");
assert.equal(token?.totalSupply, BigInt(1500));
});
Multiple Event Types
it("handles multiple event types", async () => {
const mockDb = MockDb.createMockDb();
const mintEvent = MyContract.Mint.createMockEvent({ ... });
const transferEvent = MyContract.Transfer.createMockEvent({ ... });
const burnEvent = MyContract.Burn.createMockEvent({ ... });
const updatedDb = await mockDb.processEvents([
mintEvent,
transferEvent,
burnEvent,
]);
// Assert final state
});
Debugging Tests
Log Entity State
const user = updatedDb.entities.User.get(userId);
console.log(JSON.stringify(user, null, 2));
Check Entity Exists
assert.ok(
updatedDb.entities.User.get(userId),
`User ${userId} should exist`
);
Common Issues
"Cannot read properties of undefined"
- Entity doesn't exist - check IDs match
- Entity wasn't created - verify handler logic
Type Mismatch
- Match schema types (BigInt vs number)
- Use BigInt() for BigInt fields
Missing Imports
import { TestHelpers, EntityType } from "generated";
const { MockDb, ContractName, Addresses } = TestHelpers;
Running Tests
# Run all tests
pnpm test
# Run specific test file
pnpm mocha test/transfers.test.ts
# Watch mode (with nodemon)
pnpm mocha --watch test/
Test Template
import assert from "assert";
import { TestHelpers, TokenEntity } from "generated";
const { MockDb, MyContract, Addresses } = TestHelpers;
describe("MyContract Indexer", () => {
describe("Transfer events", () => {
it("creates Transfer entity", async () => {
const mockDb = MockDb.createMockDb();
const event = MyContract.Transfer.createMockEvent({
from: Addresses.defaultAddress,
to: "0x456...",
value: BigInt(1000),
});
const updatedDb = await mockDb.processEvents([event]);
// Add assertions
});
});
});