Skip to content

Commit

Permalink
test: set up mock game for test data, use in zustand tests (#2361)
Browse files Browse the repository at this point in the history
  • Loading branch information
holic authored Mar 5, 2024
1 parent 645736d commit 884642a
Show file tree
Hide file tree
Showing 26 changed files with 1,893 additions and 46 deletions.
2 changes: 2 additions & 0 deletions packages/store-sync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/sql.js": "^1.4.4",
"@viem/anvil": "^0.0.7",
"mock-game-contracts": "workspace:*",
"tsup": "^6.7.0",
"vitest": "0.34.6"
},
Expand Down
190 changes: 146 additions & 44 deletions packages/store-sync/src/zustand/createStorageAdapter.test.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,173 @@
import { describe, expect, it } from "vitest";
import mudConfig from "../../../../e2e/packages/contracts/mud.config";
import worldRpcLogs from "../../../../test-data/world-logs.json";
import { groupLogsByBlockNumber } from "@latticexyz/block-logs-stream";
import { StoreEventsLog } from "../common";
import { RpcLog, formatLog, decodeEventLog, Hex } from "viem";
import { resolveConfig, storeEventsAbi } from "@latticexyz/store";
import { storeEventsAbi } from "@latticexyz/store";
import { createStorageAdapter } from "./createStorageAdapter";
import { createStore } from "./createStore";
import { config, deployMockGame } from "../../test/deployMockGame";
import { fetchAndStoreLogs } from "../fetchAndStoreLogs";
import { publicClient } from "../../test/common";

const tables = resolveConfig(mudConfig).tables;
describe("createStorageAdapter", async () => {
await deployMockGame();

// TODO: make test-data a proper package and export this
const blocks = groupLogsByBlockNumber(
worldRpcLogs.map((log) => {
const { eventName, args } = decodeEventLog({
abi: storeEventsAbi,
data: log.data as Hex,
topics: log.topics as [Hex, ...Hex[]],
strict: true,
});
return formatLog(log as unknown as RpcLog, { args, eventName: eventName as string }) as StoreEventsLog;
}),
);

describe("createStorageAdapter", () => {
it("sets component values from logs", async () => {
const useStore = createStore({ tables });
const useStore = createStore({ tables: config.tables });
const storageAdapter = createStorageAdapter({ store: useStore });

for (const block of blocks) {
await storageAdapter(block);
console.log("fetching blocks");
for await (const block of fetchAndStoreLogs({
storageAdapter,
publicClient,
events: storeEventsAbi,
fromBlock: 0n,
toBlock: await publicClient.getBlockNumber(),
})) {
// console.log("got block", block.blockNumber);
}

expect(useStore.getState().getRecords(tables.NumberList)).toMatchInlineSnapshot(`
expect(useStore.getState().getRecords(config.tables.Position)).toMatchInlineSnapshot(`
{
"0x746200000000000000000000000000004e756d6265724c697374000000000000:0x": {
"id": "0x746200000000000000000000000000004e756d6265724c697374000000000000:0x",
"key": {},
"keyTuple": [],
"0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x000000000000000000000000078cf0753dd50f7c56f20b3ae02719ea199be2eb": {
"id": "0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x000000000000000000000000078cf0753dd50f7c56f20b3ae02719ea199be2eb",
"key": {
"player": "0x078cf0753dd50f7C56F20B3Ae02719EA199BE2eb",
},
"keyTuple": [
"0x000000000000000000000000078cf0753dd50f7c56f20b3ae02719ea199be2eb",
],
"table": {
"keySchema": {
"player": {
"internalType": "address",
"type": "address",
},
},
"name": "Position",
"namespace": "",
"tableId": "0x74620000000000000000000000000000506f736974696f6e0000000000000000",
"valueSchema": {
"x": {
"internalType": "int32",
"type": "int32",
},
"y": {
"internalType": "int32",
"type": "int32",
},
},
},
"value": {
"x": 3,
"y": 5,
},
},
"0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x0000000000000000000000001d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e": {
"id": "0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x0000000000000000000000001d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e",
"key": {
"player": "0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e",
},
"keyTuple": [
"0x0000000000000000000000001d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e",
],
"table": {
"keySchema": {
"player": {
"internalType": "address",
"type": "address",
},
},
"name": "Position",
"namespace": "",
"tableId": "0x74620000000000000000000000000000506f736974696f6e0000000000000000",
"valueSchema": {
"x": {
"internalType": "int32",
"type": "int32",
},
"y": {
"internalType": "int32",
"type": "int32",
},
},
},
"value": {
"x": 1,
"y": -1,
},
},
"0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x000000000000000000000000328809bc894f92807417d2dad6b7c998c1afdac6": {
"id": "0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x000000000000000000000000328809bc894f92807417d2dad6b7c998c1afdac6",
"key": {
"player": "0x328809Bc894f92807417D2dAD6b7C998c1aFdac6",
},
"keyTuple": [
"0x000000000000000000000000328809bc894f92807417d2dad6b7c998c1afdac6",
],
"table": {
"keySchema": {
"player": {
"internalType": "address",
"type": "address",
},
},
"name": "Position",
"namespace": "",
"tableId": "0x74620000000000000000000000000000506f736974696f6e0000000000000000",
"valueSchema": {
"x": {
"internalType": "int32",
"type": "int32",
},
"y": {
"internalType": "int32",
"type": "int32",
},
},
},
"value": {
"x": 3,
"y": 5,
},
},
"0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x000000000000000000000000dba86119a787422c593cef119e40887f396024e2": {
"id": "0x74620000000000000000000000000000506f736974696f6e0000000000000000:0x000000000000000000000000dba86119a787422c593cef119e40887f396024e2",
"key": {
"player": "0xdBa86119a787422C593ceF119E40887f396024E2",
},
"keyTuple": [
"0x000000000000000000000000dba86119a787422c593cef119e40887f396024e2",
],
"table": {
"keySchema": {},
"name": "NumberList",
"keySchema": {
"player": {
"internalType": "address",
"type": "address",
},
},
"name": "Position",
"namespace": "",
"tableId": "0x746200000000000000000000000000004e756d6265724c697374000000000000",
"tableId": "0x74620000000000000000000000000000506f736974696f6e0000000000000000",
"valueSchema": {
"value": {
"internalType": "uint32[]",
"type": "uint32[]",
"x": {
"internalType": "int32",
"type": "int32",
},
"y": {
"internalType": "int32",
"type": "int32",
},
},
},
"value": {
"value": [
420,
69,
],
"x": 100,
"y": 100,
},
},
}
`);

expect(useStore.getState().getValue(tables.NumberList, {})).toMatchInlineSnapshot(`
expect(useStore.getState().getValue(config.tables.Terrain, { x: 3, y: 5 })).toMatchInlineSnapshot(`
{
"value": [
420,
69,
],
"terrainType": 2,
}
`);
});
Expand Down
18 changes: 18 additions & 0 deletions packages/store-sync/test/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createPublicClient, 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",
transport: http(anvilRpcUrl),
});

export const publicClient = createPublicClient({
transport: http(anvilRpcUrl),
});
33 changes: 33 additions & 0 deletions packages/store-sync/test/deployMockGame.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { execa } from "execa";
import { anvilRpcUrl, testClient } from "./common";
import mudConfig from "mock-game-contracts/mud.config";
import { resolveConfig } from "@latticexyz/store";

export const config = resolveConfig(mudConfig);

export async function deployMockGame(): Promise<void> {
const automine = await testClient.getAutomine();

if (!automine) {
console.log("turning on automine for deploy");
await testClient.setAutomine(true);
}

// TODO: build in globalSetup so we don't have to build here?
console.log("deploying mud");
const { stdout, stderr } = await execa("pnpm", ["mud", "deploy", "--rpc", anvilRpcUrl, "--saveDeployment", "false"], {
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);

if (!automine) {
console.log("turning off automine");
await testClient.setAutomine(false);
}
}
16 changes: 16 additions & 0 deletions packages/store-sync/test/globalSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { startProxy as startAnvilProxy } from "@viem/anvil";
import { anvilHost, anvilPort } from "./common";

export default async function globalSetup(): Promise<() => Promise<void>> {
const shutdownAnvilProxy = await startAnvilProxy({
host: anvilHost,
port: anvilPort,
options: {
noMining: true,
},
});

return async () => {
await shutdownAnvilProxy();
};
}
7 changes: 7 additions & 0 deletions packages/store-sync/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from "vitest/config";

export default defineConfig({
test: {
globalSetup: ["test/globalSetup.ts"],
},
});
Loading

0 comments on commit 884642a

Please sign in to comment.