### Build Matchstick from Source Source: https://github.com/limechain/matchstick/blob/main/README.md Clone the Matchstick repository and build the project using Cargo. Ensure Rust and PostgreSQL are installed. ```bash cargo build ``` -------------------------------- ### Install PostgreSQL on macOS Source: https://github.com/limechain/matchstick/blob/main/README.md Installs PostgreSQL version 14 using Homebrew and creates a symbolic link for `libpq.5.dylib` to resolve potential compatibility issues with graph-node. ```bash brew install postgresql@14 ``` ```bash ln -sf /usr/local/opt/postgresql@14/lib/postgresql@14/libpq.5.dylib /usr/local/opt/postgresql/lib/libpq.5.dylib ``` -------------------------------- ### Install PostgreSQL on Linux Source: https://github.com/limechain/matchstick/blob/main/README.md Installs PostgreSQL using the system's package manager. This command is for Debian-based distributions like Ubuntu. ```bash sudo apt install postgresql ``` -------------------------------- ### Build Matchstick Docker Image Source: https://github.com/limechain/matchstick/blob/main/README.md Builds a Docker image for Matchstick. Ensure Docker is installed and replace `` with the desired version. ```bash docker build -t matchstick . ``` -------------------------------- ### Matchstick CLI Invocation Examples Source: https://context7.com/limechain/matchstick/llms.txt Commands for running all tests, specific test suites, forcing recompilation, and generating coverage reports. Docker usage is also shown. ```bash # Run all test suites graph test ``` ```bash # Run a specific test suite (file name without extension) graph test gravity ``` ```bash # Run multiple specific test suites graph test gravity tokenLockWallet ``` ```bash # Force recompile all test sources before running graph test --recompile ``` ```bash # Generate a handler coverage report (no tests executed) graph test --coverage ``` ```bash # Docker — mount project root and run all tests docker build -t matchstick . docker run -it --rm \ --mount type=bind,source="$(pwd)",target=/matchstick \ matchstick ``` ```bash # Docker — pass arguments (e.g. run only the gravity suite) docker run -e ARGS="gravity" -it --rm \ --mount type=bind,source="$(pwd)",target=/matchstick \ matchstick ``` -------------------------------- ### Add, Get, Assert, and Remove Entity Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Demonstrates adding an entity, asserting its presence, removing it, and asserting its absence from the store. ```typescript assert.fieldEquals( GRAVATAR_ENTITY_TYPE, "23", "id", "23", ) store.remove(GRAVATAR_ENTITY_TYPE, "23") assert.notInStore(GRAVATAR_ENTITY_TYPE, "23") ``` -------------------------------- ### Add Matchstick as a Dev Dependency Source: https://github.com/limechain/matchstick/blob/main/README.md Install the matchstick-as package as a development dependency to use its test helper methods and run tests. ```bash yarn add --dev matchstick-as ``` -------------------------------- ### Using Lifecycle Hooks in Matchstick Tests Source: https://context7.com/limechain/matchstick/llms.txt Lifecycle hooks like `beforeAll`, `afterAll`, `beforeEach`, and `afterEach` are used to run setup and teardown code around test suites or individual tests. `beforeAll` runs once before any test, `afterAll` runs after the full suite, and `beforeEach`/`afterEach` run before/after each individual test. `clearStore()` is used in `afterAll` to wipe all entities. ```typescript import { beforeAll, afterAll, beforeEach, afterEach, test, clearStore, assert } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" let ENTITY_TYPE = "Gravatar" beforeAll(() => { // Runs once before any test in this file let g = new Gravatar("setup-id") g.displayName = "Setup" g.owner = Address.fromString("0x0000000000000000000000000000000000000001") g.imageUrl = "https://example.com/setup.png" g.save() }) afterAll(() => { clearStore() // Wipe all entities after the full suite }) beforeEach(() => { // Runs before each individual test }) afterEach(() => { // Runs after each individual test }) test("Entity exists from beforeAll", () => { assert.fieldEquals(ENTITY_TYPE, "setup-id", "displayName", "Setup") }) ``` -------------------------------- ### Assert Entity Count Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests asserting the count of entities of a specific type in the store, starting from zero and adding entities. ```typescript clearStore() assert.entityCount(GRAVATAR_ENTITY_TYPE, 0) let counter = 1 while (countEntities(GRAVATAR_ENTITY_TYPE) < 2) { let newGravatar = new Gravatar("id" + counter.toString()) ``` -------------------------------- ### Mocking Smart Contract Calls with `createMockedFunction` Source: https://context7.com/limechain/matchstick/llms.txt Use `createMockedFunction` to register mock return values for specific contract function calls. Argument types must precisely match the function signature. This example shows mocking a function that returns an address and another that reverts. ```typescript import { createMockedFunction, test, assert } from "matchstick-as/assembly/index" import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts" import { Gravity } from "../../generated/Gravity/Gravity" test("Mock gravity contract function", () => { let contractAddress = Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7") let expectedOwner = Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947") let bigIntParam = BigInt.fromString("1234") createMockedFunction(contractAddress, "gravatarToOwner", "gravatarToOwner(uint256):(address)") .withArgs([ethereum.Value.fromUnsignedBigInt(bigIntParam)]) .returns([ethereum.Value.fromAddress(expectedOwner)]) let gravity = Gravity.bind(contractAddress) let result = gravity.gravatarToOwner(bigIntParam) assert.addressEquals(expectedOwner, result) }) test("Mock function that reverts", () => { let contractAddress = Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7") createMockedFunction(contractAddress, "getGravatar", "getGravatar(address):(string,string)") .withArgs([ethereum.Value.fromAddress(contractAddress)]) .reverts() let result = ethereum.call( new ethereum.SmartContractCall("Gravity", contractAddress, "getGravatar", "getGravatar(address):(string,string)", [ethereum.Value.fromAddress(contractAddress)]) ) assert.assertNull(result) // null because the call reverted }) ``` -------------------------------- ### Count Entities Programmatically with `countEntities()` Source: https://context7.com/limechain/matchstick/llms.txt Use `countEntities()` to get the number of entities of a specific type in the store as an `i32`. This is useful for dynamic test logic and loop conditions that go beyond `assert.entityCount`. ```typescript import { test, countEntities, assert, clearStore } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" test("countEntities returns correct count", () => { clearStore() let i = 1 while (countEntities("Gravatar") < 5) { let g = new Gravatar(i.toString()) g.displayName = "G" + i.toString() g.owner = Address.fromString("0x000000000000000000000000000000000000000" + i.toString()) g.imageUrl = "https://example.com/" + i.toString() + ".png" g.save() i++ } assert.entityCount("Gravatar", 5) // countEntities can also be used in conditional logic: let count = countEntities("Gravatar") assert.i32Equals(5, count) }) ``` -------------------------------- ### Matchstick Configuration (`matchstick.yaml`) Source: https://context7.com/limechain/matchstick/llms.txt Configure paths for tests, libraries, and the subgraph manifest. Missing keys fall back to defaults. ```yaml # matchstick.yaml testsFolder: ./specs # default: ./tests libsFolder: ./node_modules # default: ./node_modules manifestPath: ./subgraph.yaml # default: ./subgraph.yaml ``` -------------------------------- ### Configure Docker Ignore for Matchstick Source: https://github.com/limechain/matchstick/blob/main/README.md Creates a `.dockerignore` file to prevent permission issues during Docker builds, specifically for the `binary-install-raw` module. ```bash node_modules/binary-install-raw/bin ``` -------------------------------- ### mockIpfsFile() / ipfs.cat() / ipfs.map() Source: https://context7.com/limechain/matchstick/llms.txt Mocks IPFS files, allowing you to register local files to be returned when IPFS is queried. Supports `ipfs.cat` for raw bytes and `ipfs.map` for iterating over JSON arrays. ```APIDOC ## `mockIpfsFile()` / `ipfs.cat()` / `ipfs.map()` — Mocking IPFS `mockIpfsFile()` registers a local file to be returned when IPFS is queried with a given hash. Supports both `ipfs.cat` (returns raw bytes) and `ipfs.map` (iterates over a JSON array, calling a callback for each item). ### Description Mocks IPFS file content for testing purposes, enabling verification of handlers that interact with IPFS. ### Parameters - **hash** (string) - Required - The IPFS hash to mock. - **filePath** (string) - Required - The local path to the file content. - **options** (object) - Optional - Options for `ipfs.map`. - **callback** (function) - The callback function to execute for each item in the JSON array. - **context** (Value) - Optional - Context value for the callback. - **args** (string[]) - Optional - Arguments to pass to the callback. ### Example ```typescript mockIpfsFile("catHash", "tests/ipfs/cat.json") ipfs.map("mapHash", "processGravatar", Value.fromString("Gravatar"), ["json"]) ``` ``` -------------------------------- ### Mock IPFS Files with `mockIpfsFile()` Source: https://context7.com/limechain/matchstick/llms.txt Use `mockIpfsFile()` to register local files that will be returned when IPFS is queried with a specific hash. This supports both `ipfs.cat` (raw bytes) and `ipfs.map` (iterating over JSON arrays). Ensure the local file paths are correct. ```typescript import { test, assert, clearStore, mockIpfsFile, beforeAll } from "matchstick-as/assembly/index" import { ipfs, Value } from "@graphprotocol/graph-ts" // tests/ipfs/cat.json → { "id": "1", "displayName": "Alice", "imageUrl": "https://example.com/1.png" } // tests/ipfs/map.json → [{"id":"1",...}, {"id":"2",...}, {"id":"3",...}] describe("IPFS", () => { beforeAll(() => { mockIpfsFile("catHash", "tests/ipfs/cat.json") mockIpfsFile("mapHash", "tests/ipfs/map.json") }) test("ipfs.cat loads a single entity", () => { // Your mapping handler calls ipfs.cat("catHash") internally gravatarFromIpfs() // function in your mapping that reads from IPFS assert.entityCount("Gravatar", 1) assert.fieldEquals("Gravatar", "1", "imageUrl", "https://example.com/1.png") }) test("ipfs.map processes a JSON array", () => { // ipfs.map calls 'processGravatar' callback for each JSON item ipfs.map("mapHash", "processGravatar", Value.fromString("Gravatar"), ["json"]) assert.entityCount("Gravatar", 3) assert.fieldEquals("Gravatar", "1", "displayName", "Gravatar1") assert.fieldEquals("Gravatar", "2", "displayName", "Gravatar2") assert.fieldEquals("Gravatar", "3", "displayName", "Gravatar3") }) }) ``` -------------------------------- ### Run Matchstick Tests with Docker and Arguments Source: https://github.com/limechain/matchstick/blob/main/README.md Executes Matchstick tests in Docker, passing arguments to the Matchstick process. Use the `ARGS` environment variable to specify arguments like datasource names or coverage reports. ```bash docker run -e ARGS="gravity" -it --rm --mount type=bind,source=,target=/matchstick matchstick ``` -------------------------------- ### Run Matchstick Tests with Docker Source: https://github.com/limechain/matchstick/blob/main/README.md Runs Matchstick tests within a Docker container, mounting the project directory. Replace `` with the actual path. ```bash docker run -it --rm --mount type=bind,source=,target=/matchstick matchstick ``` -------------------------------- ### Mocking Data Sources with Matchstick Source: https://github.com/limechain/matchstick/blob/main/mocks/as/token-lock-wallet-tests.txt Demonstrates how to mock data sources and set return values for testing contract interactions. This is useful for simulating external contract calls or data retrieval. ```typescript import { assert, test, newMockEvent, dataSourceMock, describe, beforeAll, afterAll, logStore, clearStore } from "matchstick-as/assembly/index" import { Address, BigInt, Bytes, DataSourceContext, store, Value } from "@graphprotocol/graph-ts" import { handleApproveTokenDestinations } from "../../src/token-lock-wallet" import { ApproveTokenDestinations } from "../../generated/templates/GraphTokenLockWallet/GraphTokenLockWallet" import { NameSignalTransaction, TokenLockWallet, GraphAccount, Subgraph } from "../../generated/schema" import { mockGraphAccount, mockNameSignalTransaction } from "./utils" describe("dataSourceMock", () => { beforeAll(() => { let addressString = "0xA16081F360e3847006dB660bae1c6d1b2e17eC2A" let address = Address.fromString(addressString) let wallet = new TokenLockWallet(address.toHexString()) // The following values should be set, because they are required fields, // and since graph-cli 0.30.0 codegen does not generate default values for required fields anymore wallet.manager = Address.zero() wallet.initHash = Address.zero() as Bytes wallet.beneficiary = Address.zero() wallet.tokenDestinationsApproved = false wallet.token = Bytes.fromHexString("0xc944e90c64b2c07662a292be6244bdf05cda44a7") // GRT wallet.managedAmount = BigInt.fromI32(0) wallet.startTime = BigInt.fromI32(0) wallet.endTime = BigInt.fromI32(0) wallet.periods = BigInt.fromI32(0) wallet.releaseStartTime = BigInt.fromI32(0) wallet.vestingCliffTime = BigInt.fromI32(0) wallet.tokensReleased = BigInt.fromI32(0) wallet.tokensWithdrawn = BigInt.fromI32(0) wallet.tokensRevoked = BigInt.fromI32(0) wallet.blockNumberCreated = BigInt.fromI32(0) wallet.txHash = Address.zero() as Bytes wallet.save() let context = new DataSourceContext() context.set("contextVal", Value.fromI32(325)) dataSourceMock.setReturnValues(addressString, "rinkeby", context) }) afterAll(() => { dataSourceMock.resetValues() }) test("Simple dataSource mocking example", () => { let addressString = "0xA16081F360e3847006dB660bae1c6d1b2e17eC2A" let address = Address.fromString(addressString) let event = changetype(newMockEvent()) let wallet = TokenLockWallet.load(address.toHexString())! assert.assertNull(wallet.tokenDestinationsApproved) handleApproveTokenDestinations(event) wallet = TokenLockWallet.load(address.toHexString())! assert.assertTrue(wallet.tokenDestinationsApproved) assert.bigIntEquals(wallet.tokensReleased, BigInt.fromI32(325)) }) }) ``` -------------------------------- ### Initialize Event with Default Metadata Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests initializing a NewGravatar event with default metadata values and asserting these defaults. ```typescript let newGravatarEvent = changetype(newMockEvent()) let DEFAULT_LOG_TYPE = "default_log_type" let DEFAULT_ADDRESS = "0xA16081F360e3847006dB660bae1c6d1b2e17eC2A" let DEFAULT_BLOCK_HASH = "0xA16081F360e3847006dB660bae1c6d1b2e17eC2A" let DEFAULT_LOG_INDEX = 1 assert.stringEquals(DEFAULT_LOG_TYPE, newGravatarEvent.logType!) assert.addressEquals(Address.fromString(DEFAULT_ADDRESS), newGravatarEvent.address) assert.bigIntEquals(BigInt.fromI32(DEFAULT_LOG_INDEX), newGravatarEvent.logIndex) assert.bytesEquals(Bytes.fromHexString(DEFAULT_BLOCK_HASH) as Bytes, newGravatarEvent.block.hash) ``` -------------------------------- ### `newMockCall()` — Creating Mock Contract Calls (Call Handlers) Source: https://context7.com/limechain/matchstick/llms.txt Creates a mock `ethereum.Call` object for testing call handlers. You can set input values for the mock call to simulate contract interactions. ```APIDOC ## `newMockCall()` ### Description Creates a mock `ethereum.Call` for testing call handlers. ### Usage ```typescript let call = changetype(newMockCall()) call.inputValues = [ new ethereum.EventParam("displayName", ethereum.Value.fromString("Carl")), new ethereum.EventParam("imageUrl", ethereum.Value.fromString("https://example.com/carl.png")), ] handleCreateGravatar(call) ``` ``` -------------------------------- ### Group Tests with `describe()` Source: https://context7.com/limechain/matchstick/llms.txt Group related tests and define setup/teardown hooks (`beforeAll`, `afterAll`, `beforeEach`, `afterEach`). Supports nested `describe()` blocks. ```typescript import { describe, test, beforeAll, afterAll, clearStore, assert } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" describe("Entity Store", () => { beforeAll(() => { let gravatar = new Gravatar("gravatarId0") gravatar.displayName = "Carl" gravatar.owner = Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947") gravatar.imageUrl = "https://example.com/carl.png" gravatar.save() }) afterAll(() => { clearStore() }) test("Can load entity from store", () => { let g = Gravatar.load("gravatarId0") assert.stringEquals("gravatarId0", g!.get("id")!.toString()) }) describe("Nested group", () => { test("Returns null for missing entity", () => { let g = Gravatar.load("doesNotExist") assert.assertNull(g) }) }) }) ``` -------------------------------- ### Create Mock Contract Call with `newMockCall()` Source: https://context7.com/limechain/matchstick/llms.txt Use `newMockCall()` to create a mock `ethereum.Call` object for testing call handlers. You can set input values for the call using `call.inputValues`. ```typescript import { test, newMockCall, assert } from "matchstick-as/assembly/index" import { ethereum } from "@graphprotocol/graph-ts" import { CreateGravatarCall } from "../../generated/Gravity/Gravity" import { handleCreateGravatar } from "../../src/gravity" test("Can save transaction from call handler", () => { let call = changetype(newMockCall()) call.inputValues = [ new ethereum.EventParam("displayName", ethereum.Value.fromString("Carl")), new ethereum.EventParam("imageUrl", ethereum.Value.fromString("https://example.com/carl.png")), ] handleCreateGravatar(call) // Default transaction hash used for the ID: 0xa16081f360e3847006db660bae1c6d1b2e17ec2a assert.fieldEquals("Transaction", "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", "displayName", "Carl") assert.fieldEquals("Transaction", "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", "imageUrl", "https://example.com/carl.png") }) ``` -------------------------------- ### Mock and Call Function with Various Argument Types Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Demonstrates how to mock a contract function with diverse argument types (int32, string, array, boolean, address, tuple) and assert its return value. ```typescript let numValue = ethereum.Value.fromI32(152) let stringValue = ethereum.Value.fromString("example string value") let arrayValue = ethereum.Value.fromI32Array([156666, 123412]) let booleanValue = ethereum.Value.fromBoolean(true) let objectValue = ethereum.Value.fromAddress(Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7")) let tupleArray: Array = [ethereum.Value.fromI32(152), ethereum.Value.fromString("string value")] let tuple = changetype(tupleArray) let tupleValue = ethereum.Value.fromTuple(tuple) let argsArray: Array = [numValue, stringValue, arrayValue, booleanValue, objectValue, tupleValue] createMockedFunction(Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947"), "funcName", "funcName(int32, string, int32[], bool, address, (int32, string)):(void)") .withArgs(argsArray) .returns([ethereum.Value.fromString("result")]) let val = ethereum.call(new ethereum.SmartContractCall("conName", Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947"), "funcName", "funcName(int32, string, int32[], bool, address, (int32, string)):(void)", argsArray))![0] ``` -------------------------------- ### Mock Gravity Contract Function Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Demonstrates mocking a specific function 'gravatarToOwner' on the Gravity contract and asserting the returned address. ```typescript let contractAddress = Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7") let expectedResult = Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947") let bigIntParam = BigInt.fromString("1234") createMockedFunction(contractAddress, "gravatarToOwner", "gravatarToOwner(uint256):(address)") .withArgs([ethereum.Value.fromUnsignedBigInt(bigIntParam)]) .returns([ethereum.Value.fromAddress(Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947"))]) let gravity = Gravity.bind(contractAddress) let result = gravity.gravatarToOwner(bigIntParam) ``` -------------------------------- ### Debug Logging with logStore, logEntity, logDataSources Source: https://context7.com/limechain/matchstick/llms.txt Utilize `logStore()`, `logEntity()`, and `logDataSources()` to print the current state of the store, a specific entity, or data source templates during test execution for debugging purposes. ```typescript import { test, logStore, logEntity, logDataSources } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" test("Debug helpers", () => { let g = new Gravatar("debug-1") g.displayName = "Debug Gravatar" g.owner = Address.fromString("0x0000000000000000000000000000000000000001") g.imageUrl = "https://example.com/debug.png" g.save() // Prints full JSON dump of every entity in the store logStore() // Prints a specific entity; `true` to include @derivedFrom fields logEntity("Gravatar", "debug-1", true) // Prints all created data sources for a named template logDataSources("Pool") }) ``` -------------------------------- ### Testing Derived Fields with Matchstick Source: https://github.com/limechain/matchstick/blob/main/mocks/as/token-lock-wallet-tests.txt Illustrates how to test derived fields in entities using Matchstick. This involves setting up related entities and verifying their relationships after modifications. ```typescript describe("@derivedFrom fields", () => { beforeAll(() => { mockGraphAccount("12") mockGraphAccount("1") }) afterAll(() => { clearStore() }) test("Derived fields example test", () => { let mainAccount = GraphAccount.load("12")! assert.assertNull(mainAccount.get("nameSignalTransactions")) assert.assertNull(mainAccount.get("operatorOf")) let operatedAccount = GraphAccount.load("1")! operatedAccount.operators = [mainAccount.id] operatedAccount.save() mockNameSignalTransaction("1234", mainAccount.id) mockNameSignalTransaction("2", mainAccount.id) mainAccount = GraphAccount.load("12")! assert.assertNotNull(mainAccount.get("nameSignalTransactions")) assert.assertNotNull(mainAccount.get("operatorOf")) assert.i32Equals(2, mainAccount.nameSignalTransactions.length) assert.stringEquals("1", mainAccount.operatorOf[0]) mockNameSignalTransaction("2345", mainAccount.id) let nst = NameSignalTransaction.load("1234")! nst.signer = "11" nst.save() store.remove("NameSignalTransaction", "2") mainAccount = GraphAccount.load("12")! assert.i32Equals(1, mainAccount.nameSignalTransactions.length) }) }) ``` -------------------------------- ### assert.dataSourceCount() / assert.dataSourceExists() Source: https://context7.com/limechain/matchstick/llms.txt Assert the number or existence of dynamically created data sources for a named template. These functions are useful for verifying that data sources are being created as expected during testing. ```APIDOC ## `assert.dataSourceCount()` / `assert.dataSourceExists()` — Testing Data Source Templates Assert the number or existence of dynamically created data sources for a named template. ### Description Asserts the count or existence of data sources for a given template name. ### Parameters - **templateName** (string) - Required - The name of the data source template. - **count** (number) - Optional - The expected number of data sources. - **message** (string) - Optional - A custom failure message. - **dataSourceId** (string) - Optional - The ID of the data source to check for existence. ### Example ```typescript assert.dataSourceCount("Pool", 1) assert.dataSourceExists("Pool", "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01") ``` ``` -------------------------------- ### Test IPFS Cat Functionality Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests the 'ipfs.cat' functionality by mocking an IPFS file and asserting that a Gravatar entity is correctly created and its image URL is set. ```typescript assert.entityCount(GRAVATAR_ENTITY_TYPE, 0) gravatarFromIpfs() assert.entityCount(GRAVATAR_ENTITY_TYPE, 1) assert.fieldEquals(GRAVATAR_ENTITY_TYPE, "1", "imageUrl", "https://example.com/image1.png") ``` -------------------------------- ### Mock IPFS File Content Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Mocks the content of an IPFS file for testing purposes. Use this to simulate fetching data from IPFS without actual network requests. ```typescript mockIpfsFile("ipfsCatFileHash", "tests/ipfs/cat.json") mockIpfsFile("ipfsMapFileHash", "tests/ipfs/map.json") ``` -------------------------------- ### Generate Coverage Report with graph test --coverage Source: https://context7.com/limechain/matchstick/llms.txt Run `graph test --coverage` to generate a report indicating which mapping handlers are called in at least one test suite. This helps identify untested handlers. ```bash # Generate coverage report graph test --coverage # Expected output: # Handlers for source 'Gravity': # Handler 'handleNewGravatar' is tested. # Handler 'handleCreateGravatar' is tested. # Handler 'handleUpdateGravatar' is not tested. # Test coverage: 66.7% (2/3 handlers). # # Global test coverage: 66.7% (2/3 handlers). ``` -------------------------------- ### Mocking dataSource Context with setReturnValues Source: https://context7.com/limechain/matchstick/llms.txt Use `dataSourceMock.setReturnValues()` to mock the return values of `dataSource.address()`, `dataSource.network()`, and `dataSource.context()`. This is useful for tests that need to exercise handlers accessing data source context. ```typescript import { test, assert } from "matchstick-as/assembly/index" import { dataSourceMock, DataSourceContext, dataSource } from "@graphprotocol/graph-ts" test("dataSource context is mocked correctly", () => { let ctx = new DataSourceContext() ctx.setString("poolFee", "3000") dataSourceMock.setReturnValues( "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01", // address "mainnet", // network ctx, // context ) assert.stringEquals("mainnet", dataSource.network()) assert.stringEquals( "0xabcdef0123456789abcdef0123456789abcdef01", dataSource.address().toHexString(), ) }) ``` -------------------------------- ### Assert Data Source Count and Existence Source: https://context7.com/limechain/matchstick/llms.txt Use `assert.dataSourceCount()` and `assert.dataSourceExists()` to verify dynamically created data sources for a named template. Custom failure messages can be provided for clearer test output. ```typescript import { test, assert, clearStore } from "matchstick-as/assembly/index" import { dataSource } from "@graphprotocol/graph-ts" import { handlePoolCreated } from "../../src/factory" import { newMockEvent } from "matchstick-as/assembly/index" import { PoolCreated } from "../../generated/Factory/Factory" import { ethereum, Address } from "@graphprotocol/graph-ts" test("Data source template created correctly", () => { let event = changetype(newMockEvent()) event.parameters = [ new ethereum.EventParam("pool", ethereum.Value.fromAddress( Address.fromString("0xAbCdEf0123456789AbCdEf0123456789AbCdEf01") )), ] handlePoolCreated(event) // Assert a specific data source template was created assert.dataSourceCount("Pool", 1) assert.dataSourceExists("Pool", "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01") // With custom failure messages assert.dataSourceCount("Pool", 1, "Expected one Pool data source") assert.dataSourceExists("Pool", "0xAbCdEf0123456789AbCdEf0123456789AbCdEf01", "Pool data source should exist") }) ``` -------------------------------- ### `assert.equals()` — Asserting ethereum.Value Equality Source: https://context7.com/limechain/matchstick/llms.txt Compares two `ethereum.Value` objects for equality, regardless of their concrete type. Useful for comparing return values from contract calls. ```APIDOC ## `assert.equals(value1: ethereum.Value, value2: ethereum.Value, customMessage?: string)` ### Description Compares two `ethereum.Value` objects for equality, regardless of their concrete type. ### Usage ```typescript let result = ethereum.call(...) assert.equals(ethereum.Value.fromString("Gravity"), result[0]) assert.equals(ethereum.Value.fromString("Gravity"), result[0], "Contract name should be Gravity") ``` ``` -------------------------------- ### Handle Create Gravatar Event Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Handles the creation of a Gravatar event with specified display name and image URL. Asserts the field values after handling. ```typescript call.inputValues = [new ethereum.EventParam("displayName", ethereum.Value.fromString("name")), new ethereum.EventParam("imageUrl", ethereum.Value.fromString("example.com"))] handleCreateGravatar(call) assert.fieldEquals(TRANSACTION_ENTITY_TYPE, "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", "displayName", "name") assert.fieldEquals(TRANSACTION_ENTITY_TYPE, "0xa16081f360e3847006db660bae1c6d1b2e17ec2a", "imageUrl", "example.com") ``` -------------------------------- ### Define a Unit Test with `test()` Source: https://context7.com/limechain/matchstick/llms.txt Register a named test case using `test()` from `matchstick-as`. An optional third argument marks the test as expected to fail. ```typescript import { test, assert } from "matchstick-as/assembly/index" import { BigInt } from "@graphprotocol/graph-ts" test("Adds two BigInts correctly", () => { let a = BigInt.fromI32(10) let b = BigInt.fromI32(32) assert.bigIntEquals(a.plus(b), BigInt.fromI32(42)) }) // Test expected to fail — passes only if the body throws test("Should throw an error", () => { throw new Error() }, true) ``` -------------------------------- ### Creating Mock Ethereum Events with `newMockEvent` Source: https://context7.com/limechain/matchstick/llms.txt The `newMockEvent()` function generates a generic `ethereum.Event` that can be cast to a specific event type and populated with custom parameters. This is useful for testing event handlers. ```typescript import { test, newMockEvent, assert } from "matchstick-as/assembly/index" import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts" import { NewGravatar } from "../../generated/Gravity/Gravity" import { handleNewGravatar } from "../../src/gravity" test("Handle NewGravatar event", () => { let mockEvent = changetype(newMockEvent()) // Override default metadata mockEvent.address = Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7") mockEvent.logIndex = BigInt.fromI32(1) mockEvent.block.hash = Bytes.fromHexString("0xA16081F360e3847006dB660bae1c6d1b2e17eC2A") as Bytes // Set event-specific parameters mockEvent.parameters = [ new ethereum.EventParam("id", ethereum.Value.fromI32(0xdead)), new ethereum.EventParam("owner", ethereum.Value.fromAddress(Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7"))), new ethereum.EventParam("displayName", ethereum.Value.fromString("Gravatar 0xdead")), new ethereum.EventParam("imageUrl", ethereum.Value.fromString("https://example.com/image0xdead.png")), ] handleNewGravatar(mockEvent) assert.fieldEquals("Gravatar", "0xdead", "displayName", "Gravatar 0xdead") assert.fieldEquals("Gravatar", "0xdead", "imageUrl", "https://example.com/image0xdead.png") }) ``` -------------------------------- ### Assert `ethereum.Value` Equality with `assert.equals()` Source: https://context7.com/limechain/matchstick/llms.txt Compare two `ethereum.Value` objects for equality, irrespective of their underlying concrete type. This assertion can also accept a custom failure message. ```typescript import { test, assert, createMockedFunction } from "matchstick-as/assembly/index" import { Address, ethereum } from "@graphprotocol/graph-ts" test("assert.equals on ethereum.Value", () => { let contractAddress = Address.fromString("0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947") createMockedFunction(contractAddress, "getName", "getName():(string)") .withArgs([]) .returns([ethereum.Value.fromString("Gravity")]) let result = ethereum.call( new ethereum.SmartContractCall("Gravity", contractAddress, "getName", "getName():(string)", []) )! assert.equals(ethereum.Value.fromString("Gravity"), result[0]) // With custom failure message assert.equals(ethereum.Value.fromString("Gravity"), result[0], "Contract name should be Gravity") }) ``` -------------------------------- ### Assert Entity Count with `assert.entityCount()` Source: https://context7.com/limechain/matchstick/llms.txt Verify the exact number of entities of a given type currently present in the store. This is useful for ensuring data integrity after operations. The store can be cleared using `clearStore()` before counting. ```typescript import { test, assert, clearStore, countEntities } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" test("entityCount assertion", () => { clearStore() assert.entityCount("Gravatar", 0) let counter = 1 while (countEntities("Gravatar") < 3) { let g = new Gravatar("id" + counter.toString()) g.displayName = "Gravatar " + counter.toString() g.owner = Address.fromString("0x000000000000000000000000000000000000000" + counter.toString()) g.imageUrl = "https://example.com/" + counter.toString() + ".png" g.save() counter++ } assert.entityCount("Gravatar", 3) }) ``` -------------------------------- ### clearStore() Source: https://context7.com/limechain/matchstick/llms.txt Resets the entity store by wiping all entities. This is crucial for preventing state leakage between tests, typically used in `afterAll()` or `afterEach()` hooks. ```APIDOC ## `clearStore()` — Resetting the Entity Store Wipes all entities from the global in-memory store. Typically called in `afterAll()` or `afterEach()` to prevent state leaking between tests. ### Description Clears all entities from the test store, ensuring a clean state for subsequent tests. ### Example ```typescript clearStore() ``` ``` -------------------------------- ### Test IPFS Map Functionality Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests the 'ipfs.map' functionality for processing multiple Gravatar entries from an IPFS file. Asserts that the correct number of entities are created and their display names are set. ```typescript assert.entityCount(GRAVATAR_ENTITY_TYPE, 0) ipfs.map("ipfsMapFileHash", 'processGravatar', Value.fromString('Gravatar'), ['json']) assert.entityCount(GRAVATAR_ENTITY_TYPE, 3) assert.fieldEquals(GRAVATAR_ENTITY_TYPE, "1", "displayName", "Gravatar1") assert.fieldEquals(GRAVATAR_ENTITY_TYPE, "2", "displayName", "Gravatar2") assert.fieldEquals(GRAVATAR_ENTITY_TYPE, "3", "displayName", "Gravatar3") ``` -------------------------------- ### `assert.entityCount()` — Asserting Entity Count Source: https://context7.com/limechain/matchstick/llms.txt Asserts the exact number of entities of a given type currently held in the store. Useful for verifying the total number of entities created or modified. ```APIDOC ## `assert.entityCount(entityType: string, count: number)` ### Description Asserts the exact number of entities of a given type currently held in the store. ### Usage ```typescript clearStore() assert.entityCount("Gravatar", 0) // ... create some entities ... assert.entityCount("Gravatar", 3) ``` ``` -------------------------------- ### Reset Entity Store with `clearStore()` Source: https://context7.com/limechain/matchstick/llms.txt Call `clearStore()` to wipe all entities from the in-memory store. This is crucial for preventing state leakage between tests, typically used in `afterAll()` or `afterEach()` hooks. ```typescript import { test, clearStore, assert } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" test("clearStore removes all entities", () => { let g = new Gravatar("temp") g.displayName = "Temp" g.owner = Address.fromString("0x0000000000000000000000000000000000000001") g.imageUrl = "https://example.com/temp.png" g.save() assert.entityCount("Gravatar", 1) clearStore() assert.entityCount("Gravatar", 0) }) ``` -------------------------------- ### Save Transaction from Call Handler Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Illustrates saving transaction data initiated by a CreateGravatar call handler. ```typescript let call = changetype(newMockCall()) ``` -------------------------------- ### countEntities() Source: https://context7.com/limechain/matchstick/llms.txt Programmatically counts the number of entities of a given type in the store. Returns an `i32` and is useful for dynamic test logic. ```APIDOC ## `countEntities()` — Counting Entities Programmatically Returns the number of entities of a given type in the store as an `i32`. Useful for loop conditions or dynamic test logic beyond what `assert.entityCount` covers. ### Description Returns the total count of entities of a specified type currently in the store. ### Parameters - **entityType** (string) - Required - The type of entity to count. ### Returns - **count** (i32) - The number of entities of the specified type. ### Example ```typescript let count = countEntities("Gravatar") ``` ``` -------------------------------- ### Assert Entity Absence with `assert.notInStore()` Source: https://context7.com/limechain/matchstick/llms.txt Check if an entity of a specific type and ID does not exist in the store. This is useful after removing an entity. An optional custom failure message can be provided. ```typescript import { test, assert } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address, store } from "@graphprotocol/graph-ts" test("notInStore assertion", () => { let g = new Gravatar("99") g.displayName = "Bob" g.owner = Address.fromString("0x0000000000000000000000000000000000000002") g.imageUrl = "https://example.com/bob.png" g.save() assert.fieldEquals("Gravatar", "99", "displayName", "Bob") store.remove("Gravatar", "99") assert.notInStore("Gravatar", "99") // entity was removed // With a custom failure message assert.notInStore("Gravatar", "ghost", "ghost should not exist") }) ``` -------------------------------- ### `assert.notInStore()` — Asserting Entity Absence Source: https://context7.com/limechain/matchstick/llms.txt Asserts that no entity of the given type with the given ID exists in the store. Useful for verifying that entities have been correctly removed. ```APIDOC ## `assert.notInStore(entityType: string, entityId: string, customMessage?: string)` ### Description Asserts that no entity of the given type with the given ID exists in the store. ### Usage ```typescript store.remove("Gravatar", "99") assert.notInStore("Gravatar", "99") // entity was removed assert.notInStore("Gravatar", "ghost", "ghost should not exist") ``` ``` -------------------------------- ### Mock New Gravatar Events Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests the handling of multiple new Gravatar events. It asserts the entity count and specific field values for created gravatars. ```typescript let newGravatarEvent = createNewGravatarEvent( 0xdead, "0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7", "Gravatar 0xdead", "https://example.com/image0xdead.png" ) let anotherGravatarEvent = createNewGravatarEvent( 0xbeef, "0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7", "Gravatar 0xbeef", "https://example.com/image0xbeef.png" ) handleNewGravatars([newGravatarEvent, anotherGravatarEvent]) assert.entityCount(GRAVATAR_ENTITY_TYPE, 2) assert.fieldEquals(GRAVATAR_ENTITY_TYPE, "0xdead", "displayName", "Gravatar 0xdead") assert.fieldEquals(GRAVATAR_ENTITY_TYPE, "0xbeef", "displayName", "Gravatar 0xbeef") ``` -------------------------------- ### Load Gravatar Entity Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests loading a Gravatar entity from the store using its ID and asserting a specific field. ```typescript let retrievedGravatar = Gravatar.load("gravatarId0") assert.stringEquals("gravatarId0", retrievedGravatar!.get("id")!.toString()) ``` -------------------------------- ### Update Event Metadata Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests updating the metadata of a NewGravatar event and asserting the updated values. ```typescript let newGravatarEvent = changetype(newMockEvent()) let UPDATED_LOG_TYPE = "updated_log_type" let UPDATED_ADDRESS = "0xB16081F360e3847006dB660bae1c6d1b2e17eC2A" let UPDATED_BLOCK_HASH = "0xC16081F360e3847006dB660bae1c6d1b2e17eC2A" let UPDATED_LOG_INDEX = 42 newGravatarEvent.logType = UPDATED_LOG_TYPE newGravatarEvent.address = Address.fromString(UPDATED_ADDRESS) newGravatarEvent.block.hash = Bytes.fromHexString( UPDATED_BLOCK_HASH, ) as Bytes newGravatarEvent.logIndex = BigInt.fromI32(UPDATED_LOG_INDEX) assert.stringEquals(UPDATED_LOG_TYPE, newGravatarEvent.logType!) assert.addressEquals(Address.fromString(UPDATED_ADDRESS), newGravatarEvent.address) assert.bigIntEquals(BigInt.fromI32(UPDATED_LOG_INDEX), newGravatarEvent.logIndex) assert.bytesEquals(Bytes.fromHexString(UPDATED_BLOCK_HASH) as Bytes, newGravatarEvent.block.hash) ``` -------------------------------- ### Assert Entity Field Value with `assert.fieldEquals()` Source: https://context7.com/limechain/matchstick/llms.txt Verify that a stored entity's field matches a specific string value. This assertion fails if the entity type, ID, field name, or value does not match. An optional custom failure message can be provided. ```typescript import { test, assert } from "matchstick-as/assembly/index" import { Gravatar } from "../../generated/schema" import { Address } from "@graphprotocol/graph-ts" test("fieldEquals assertion", () => { let g = new Gravatar("42") g.displayName = "Alice" g.owner = Address.fromString("0x0000000000000000000000000000000000000001") g.imageUrl = "https://example.com/alice.png" g.save() assert.fieldEquals("Gravatar", "42", "displayName", "Alice") assert.fieldEquals("Gravatar", "42", "imageUrl", "https://example.com/alice.png") // With a custom failure message (overload) assert.fieldEquals("Gravatar", "42", "displayName", "Alice", "displayName should be Alice") }) ``` -------------------------------- ### Gracefully Handle Gravatar Save Failure Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt Tests the graceful failure of saving Gravatar data when the 'getGravatar' function reverts, ensuring existing data is not altered. ```typescript let contractAddress = Address.fromString("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7") createMockedFunction(contractAddress, "getGravatar", "getGravatar(address):(string,string)") .withArgs([ethereum.Value.fromAddress(contractAddress)]) .reverts() trySaveGravatarFromContract("48") ``` -------------------------------- ### Test Error Throwing Source: https://github.com/limechain/matchstick/blob/main/mocks/as/gravity-tests.txt A basic test case that explicitly throws an error to verify error handling mechanisms. ```typescript throw new Error() ```