mod_test.ts
1 import { assertEquals, assertNotEquals, equal } from "@std/assert"; 2 import { assertInstanceOf } from "@std/assert/instance-of"; 3 4 import { MemStore } from "@massmarket/store/mem"; 5 import { 6 createTestBlockchainClient, 7 createTestRelayClient, 8 } from "@massmarket/client/test"; 9 import { RelayResponseError } from "@massmarket/client"; 10 import { type codec, randomBytes } from "@massmarket/utils"; 11 12 import StateManager from "./mod.ts"; 13 import { assertRejects } from "@std/assert/rejects"; 14 15 // we create the blockchain client outside of the tests since viem has a ws leak 16 const blockchainClient = createTestBlockchainClient(); 17 const relayClient = await createTestRelayClient(blockchainClient); 18 19 const root = new Map(Object.entries({ 20 Tags: new Map(), 21 Orders: new Map(), 22 Accounts: new Map(), 23 Inventory: new Map(), 24 Listings: new Map(), 25 Manifest: new Map(), 26 SchemeVersion: 1, 27 })); 28 29 Deno.test("Database Testings", async (t) => { 30 const store = new MemStore(); 31 const sm = new StateManager({ 32 store, 33 id: relayClient.shopId, 34 defaultState: root, 35 }); 36 37 await sm.open(); 38 39 await t.step("add a relay and set a key and retrieve it", async () => { 40 // connect to the relay 41 const { resolve, promise } = Promise.withResolvers(); 42 sm.events.on((manifestPatch) => { 43 resolve(manifestPatch); 44 }, ["Manifest"]); 45 46 sm.addConnection(relayClient); 47 // wait for manifest to be received 48 await promise; 49 const testAddr = Uint8Array.from([ 50 0xf0, 51 0xf1, 52 0xf2, 53 0x03, 54 0x04, 55 0x05, 56 0xf6, 57 0xf7, 58 0xf8, 59 0x09, 60 0x0a, 61 0x0b, 62 0xfc, 63 0xfd, 64 0xfe, 65 0x0f, 66 0x01, 67 0x02, 68 0xf3, 69 0xf4, 70 ]); 71 72 const testCurrency = new Map<string, codec.CodecValue>([ 73 ["Address", testAddr], 74 ["ChainID", 1337], 75 ]); 76 await sm.set( 77 ["Manifest", "PricingCurrency"], 78 testCurrency, 79 ); 80 const value = await sm.get(["Manifest", "PricingCurrency"]); 81 assertEquals( 82 value, 83 new Map<string, codec.CodecValue>([ 84 ["Address", testAddr], 85 ["ChainID", 1337], 86 ]), 87 ); 88 }); 89 90 await t.step( 91 "Make sure stateManager throws an error when a patch is rejected", 92 async () => { 93 const result = await assertRejects(() => sm.set(["Trash"], "Bad Value")); 94 assertInstanceOf(result, RelayResponseError); 95 }, 96 ); 97 await t.step("Make sure we can do more then one bad write", async () => { 98 const result = await assertRejects(() => 99 sm.set(["Trash"], "Another Bad Value") 100 ); 101 assertInstanceOf(result, RelayResponseError); 102 }); 103 104 await sm.close(); 105 106 await t.step("Make sure we can close the state manager", async () => { 107 const pricingCurrencyPath = ["Manifest", "PricingCurrency"]; 108 const nonce = relayClient.keyCardNonce; 109 const nsm = new StateManager({ 110 store, 111 id: relayClient.shopId, 112 }); 113 await nsm.open(); 114 nsm.addConnection(relayClient); 115 assertEquals( 116 nonce, 117 relayClient.keyCardNonce, 118 "the new state manager should have loaded the nonce", 119 ); 120 const oldValue = await nsm.get(pricingCurrencyPath); 121 await nsm.close(); 122 123 // Test that we can set new values after reopening 124 const reopenedSm = new StateManager({ 125 store, 126 id: relayClient.shopId, 127 }); 128 await reopenedSm.open(); 129 reopenedSm.addConnection(relayClient); 130 131 // Set a new value 132 const newTestValue = new Map<string, codec.CodecValue>([ 133 ["Address", randomBytes(20)], 134 ["ChainID", 1337], 135 ]); 136 await reopenedSm.set(pricingCurrencyPath, newTestValue); 137 138 // wait until we see the new value from the relay 139 await new Promise((resolve) => { 140 reopenedSm.events.on((val) => { 141 if (equal(val, newTestValue)) { 142 resolve(void 0); 143 } 144 }, pricingCurrencyPath); 145 }); 146 147 // Verify the value was set correctly 148 const retrievedValue = await reopenedSm.get(pricingCurrencyPath); 149 assertNotEquals( 150 retrievedValue, 151 oldValue, 152 `should not be the old value`, 153 ); 154 assertEquals( 155 retrievedValue, 156 newTestValue, 157 `should be able to set and get values after reopening`, 158 ); 159 await reopenedSm.close(); 160 }); 161 162 await relayClient.disconnect(); 163 });