Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
holic committed Oct 1, 2024
1 parent 0eb32e4 commit 0b05c0c
Show file tree
Hide file tree
Showing 14 changed files with 687 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from "./getBurnerPrivateKey";
export * from "./getNonceManager";
export * from "./getNonceManagerId";
export * from "./hexToResource";
export * from "./logSort";
export * from "./LruMap";
export * from "./readHex";
export * from "./resourceToLabel";
Expand Down
16 changes: 16 additions & 0 deletions packages/common/src/logSort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Log } from "viem";

export function logSort(a: Log, b: Log): number {
if (a.blockNumber === b.blockNumber) {
if (a.logIndex === b.logIndex) return 0;
if (a.logIndex == null) return 1;
if (b.logIndex == null) return -1;
return a.logIndex - b.logIndex;
}

if (a.blockNumber == null) return 1;
if (b.blockNumber == null) return -1;
if (a.blockNumber > b.blockNumber) return 1;
if (a.blockNumber < b.blockNumber) return -1;
return 0;
}
3 changes: 1 addition & 2 deletions packages/store-sync/test/logsToBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ export function logsToBlocks(
topics: log.topics as [Hex, ...Hex[]],
strict: true,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return formatLog(log as any as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog;
return formatLog(log as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog;
}),
);
}
2 changes: 2 additions & 0 deletions packages/store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@
"@types/ejs": "^3.1.1",
"@types/mocha": "^9.1.1",
"@types/node": "^18.15.11",
"@viem/anvil": "^0.0.7",
"ds-test": "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0",
"forge-std": "https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1",
"mock-game-contracts": "workspace:*",
"solhint": "^3.3.7",
"tsup": "^6.7.0",
"tsx": "^3.12.6",
Expand Down
180 changes: 180 additions & 0 deletions packages/store/ts/flattenStoreLogs.test.ts

Large diffs are not rendered by default.

323 changes: 323 additions & 0 deletions packages/store/ts/getStoreLogs.test.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/store/ts/getStoreLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export type GetStoreLogsReturnType<
export type GetStoreLogsErrorType = GetLogsErrorType;

/**
* Returns a list of store event logs matching the provided parameters.
* Returns an unordered list of store event logs matching the provided parameters.
*
* @param client - Client to use
* @param parameters - {@link GetStoreLogsParameters}
Expand Down
16 changes: 16 additions & 0 deletions packages/store/ts/test/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createTestClient, http } from "viem";

export const anvilHost = "127.0.0.1";
export const anvilPort = 8555;

// ID of the current test worker. Used by the `@viem/anvil` proxy server.
export const poolId = Number(process.env.VITEST_POOL_ID ?? 1);

export const anvilRpcUrl = `http://${anvilHost}:${anvilPort}/${poolId}`;

export const testClient = createTestClient({
mode: "anvil",
// TODO: if tests get slow, try switching to websockets?
transport: http(anvilRpcUrl),
pollingInterval: 10,
});
19 changes: 19 additions & 0 deletions packages/store/ts/test/globalSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { startProxy as startAnvilProxy } from "@viem/anvil";
import { anvilHost, anvilPort } from "./common";
import { execa } from "execa";

export default async function globalSetup(): Promise<() => Promise<void>> {
console.log("building mock game");
await execa("pnpm", ["run", "build"], {
cwd: `${__dirname}/../../../../test/mock-game-contracts`,
});

const shutdownAnvilProxy = await startAnvilProxy({
host: anvilHost,
port: anvilPort,
});

return async () => {
await shutdownAnvilProxy();
};
}
35 changes: 35 additions & 0 deletions packages/store/ts/test/mockGame.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { execa } from "execa";
import { anvilRpcUrl } from "./common";
import { Hex, isHex } from "viem";
import config from "mock-game-contracts/mud.config";
import worldAbi from "mock-game-contracts/out/IWorld.sol/IWorld.abi.json";

export { config, worldAbi };

export async function deployMockGame(): Promise<Hex> {
console.log("deploying mock game to", anvilRpcUrl);
const { stdout, stderr } = await execa(
"pnpm",
// skip build because its slow and we do it in global setup
// if we don't skip build here, it regenerates ABIs which cause the tests to re-run (because we import the ABI here), which re-runs this deploy...
["mud", "deploy", "--rpc", anvilRpcUrl, "--saveDeployment", "false", "--skipBuild"],
{
cwd: `${__dirname}/../../../../test/mock-game-contracts`,
env: {
// anvil default account
PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
DEBUG: "mud:*",
},
},
);
if (stderr) console.error(stderr);
if (stdout) console.log(stdout);

const [, worldAddress] = stdout.match(/worldAddress: '(0x[0-9a-f]+)'/i) ?? [];
if (!isHex(worldAddress)) {
throw new Error("world address not found in output, did the deploy fail?");
}
console.log("deployed mock game", worldAddress);

return worldAddress;
}
18 changes: 18 additions & 0 deletions packages/store/ts/test/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { beforeAll, beforeEach } from "vitest";
import { testClient } from "./common";

// Some test suites deploy contracts in a `beforeAll` handler, so we restore chain state here.
beforeAll(async () => {
const state = await testClient.dumpState();
return async (): Promise<void> => {
await testClient.loadState({ state });
};
});

// Some tests execute transactions, so we restore chain state here.
beforeEach(async () => {
const state = await testClient.dumpState();
return async (): Promise<void> => {
await testClient.loadState({ state });
};
});
12 changes: 12 additions & 0 deletions packages/store/ts/test/summarizeLogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { logSort, resourceToLabel, hexToResource } from "@latticexyz/common";
import { StoreLog } from "../storeLog";

export function summarizeLogs(logs: StoreLog[]) {
return logs
.slice()
.sort(logSort)
.map(
({ eventName, args: { tableId, keyTuple } }) =>
`${eventName} ${resourceToLabel(hexToResource(tableId))} (${keyTuple})`,
);
}
13 changes: 12 additions & 1 deletion packages/store/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ import { defineConfig } from "vitest/config";

export default defineConfig({
test: {
globalSetup: "vitestSetup.ts",
globalSetup: ["vitestSetup.ts", "ts/test/globalSetup.ts"],
setupFiles: ["ts/test/setup.ts"],
// Temporarily set a low teardown timeout because anvil hangs otherwise
// Could move this timeout to anvil setup after https://github.com/wevm/anvil.js/pull/46
teardownTimeout: 500,
hookTimeout: 15000,
},
server: {
watch: {
// we build+import this file in test setup, which causes vitest to restart in a loop unless we ignore it here
ignored: ["**/test/mock-game-contracts/out/IWorld.sol/IWorld.abi.json"],
},
},
});
Loading

0 comments on commit 0b05c0c

Please sign in to comment.