diff options
| author | Adam Soltys <[email protected]> | 2026-02-24 13:18:42 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-02-24 13:18:42 -0800 |
| commit | ad7b09b43323d0ffc0a8ddabb43e4838a184c697 (patch) | |
| tree | fbf2a59f81771b2938f474c8e7b35a497d2960e4 /test/preload.ts | |
| parent | 9e97e040617bfa0b40150c0eba298bf186bbeeaf (diff) | |
| download | coinos-server-ad7b09b43323d0ffc0a8ddabb43e4838a184c697.tar.gz coinos-server-ad7b09b43323d0ffc0a8ddabb43e4838a184c697.zip | |
formatting
Diffstat (limited to 'test/preload.ts')
| -rw-r--r-- | test/preload.ts | 639 |
1 files changed, 354 insertions, 285 deletions
diff --git a/test/preload.ts b/test/preload.ts index a3d3cbb9..01629d97 100644 --- a/test/preload.ts +++ b/test/preload.ts @@ -7,307 +7,376 @@ if (process.env.INTEGRATION) { // Skip all mocking — use real services globalThis.__testStore = { kvStore: {}, listStore: {}, setStore: {} }; } else { + let kvStore: Record<string, string> = {}; + let listStore: Record<string, string[]> = {}; + let setStore: Record<string, Set<string>> = {}; -let kvStore: Record<string, string> = {}; -let listStore: Record<string, string[]> = {}; -let setStore: Record<string, Set<string>> = {}; + globalThis.__testStore = { kvStore, listStore, setStore }; -globalThis.__testStore = { kvStore, listStore, setStore }; - -const makeMulti = () => { - const ops: Array<() => Promise<any>> = []; - const chain: any = { - set: (k: string, v: string) => { - ops.push(async () => { globalThis.__testStore.kvStore[k] = v; }); - return chain; - }, - lPush: (k: string, v: string) => { - ops.push(async () => { - const ls = globalThis.__testStore.listStore; - if (!ls[k]) ls[k] = []; - ls[k].unshift(v); - }); - return chain; - }, - del: (k: string) => { - ops.push(async () => { delete globalThis.__testStore.kvStore[k]; }); - return chain; - }, - lRem: (k: string, _count: number, v: string) => { - ops.push(async () => { - const ls = globalThis.__testStore.listStore; - if (ls[k]) { - const idx = ls[k].indexOf(v); - if (idx >= 0) ls[k].splice(idx, 1); - } - }); - return chain; - }, - sRem: (k: string, v: string) => { - ops.push(async () => globalThis.__testStore.setStore[k]?.delete(v)); - return chain; - }, - exec: async () => { - for (const op of ops) await op(); - return []; - }, - }; - return chain; -}; - -mock.module("$lib/db", () => { - const kv = () => globalThis.__testStore.kvStore; - const ls = () => globalThis.__testStore.listStore; - const ss = () => globalThis.__testStore.setStore; - const g = async (k: string) => { - const v = kv()[k] ?? null; - if (v === null) return null; - try { return JSON.parse(v); } catch { return v; } - }; - const s = (k: string, v: any) => { - if (k === "user:null" || k === "user:undefined") throw new Error("null user"); - kv()[k] = JSON.stringify(v); - }; - const gf = async (k: string) => { - const v = kv()[k] ?? null; - if (v === null) return null; - try { return JSON.parse(v); } catch { return v; } - }; - return { - db: { - get: async (k: string) => kv()[k] ?? null, - set: async (k: string, v: string, opts?: any) => { - if (opts?.NX && kv()[k] !== undefined) return null; - kv()[k] = v; - return "OK"; + const makeMulti = () => { + const ops: Array<() => Promise<any>> = []; + const chain: any = { + set: (k: string, v: string) => { + ops.push(async () => { + globalThis.__testStore.kvStore[k] = v; + }); + return chain; }, - del: async (k: string) => { delete kv()[k]; return 1; }, - exists: async (k: string) => (kv()[k] !== undefined ? 1 : 0), - lPush: async (k: string, v: string) => { - if (!ls()[k]) ls()[k] = []; - ls()[k].unshift(v); - return ls()[k].length; + lPush: (k: string, v: string) => { + ops.push(async () => { + const ls = globalThis.__testStore.listStore; + if (!ls[k]) ls[k] = []; + ls[k].unshift(v); + }); + return chain; }, - lRem: async (k: string, _count: number, v: string) => { - if (!ls()[k]) return 0; - const idx = ls()[k].indexOf(v); - if (idx >= 0) { ls()[k].splice(idx, 1); return 1; } - return 0; + del: (k: string) => { + ops.push(async () => { + delete globalThis.__testStore.kvStore[k]; + }); + return chain; }, - lRange: async (k: string, start: number, end: number) => { - if (!ls()[k]) return []; - if (end === -1) return ls()[k].slice(start); - return ls()[k].slice(start, end + 1); + lRem: (k: string, _count: number, v: string) => { + ops.push(async () => { + const ls = globalThis.__testStore.listStore; + if (ls[k]) { + const idx = ls[k].indexOf(v); + if (idx >= 0) ls[k].splice(idx, 1); + } + }); + return chain; }, - lPos: async (k: string, v: string) => { - if (!ls()[k]) return null; - const idx = ls()[k].indexOf(v); - return idx >= 0 ? idx : null; + sRem: (k: string, v: string) => { + ops.push(async () => globalThis.__testStore.setStore[k]?.delete(v)); + return chain; }, - sAdd: async (k: string, ...vals: string[]) => { - if (!ss()[k]) ss()[k] = new Set(); - for (const v of vals) ss()[k].add(v); - return vals.length; + exec: async () => { + for (const op of ops) await op(); + return []; }, - sRem: async (k: string, v: string) => ss()[k]?.delete(v) ? 1 : 0, - sIsMember: async (k: string, v: string) => ss()[k]?.has(v) ?? false, - sMembers: async (k: string) => (ss()[k] ? [...ss()[k]] : []), - incrBy: async (k: string, n: number) => { - const v = Number.parseInt(kv()[k] || "0") + n; - kv()[k] = String(v); + }; + return chain; + }; + + mock.module("$lib/db", () => { + const kv = () => globalThis.__testStore.kvStore; + const ls = () => globalThis.__testStore.listStore; + const ss = () => globalThis.__testStore.setStore; + const g = async (k: string) => { + const v = kv()[k] ?? null; + if (v === null) return null; + try { + return JSON.parse(v); + } catch { return v; + } + }; + const s = (k: string, v: any) => { + if (k === "user:null" || k === "user:undefined") throw new Error("null user"); + kv()[k] = JSON.stringify(v); + }; + const gf = async (k: string) => { + const v = kv()[k] ?? null; + if (v === null) return null; + try { + return JSON.parse(v); + } catch { + return v; + } + }; + return { + db: { + get: async (k: string) => kv()[k] ?? null, + set: async (k: string, v: string, opts?: any) => { + if (opts?.NX && kv()[k] !== undefined) return null; + kv()[k] = v; + return "OK"; + }, + del: async (k: string) => { + delete kv()[k]; + return 1; + }, + exists: async (k: string) => (kv()[k] !== undefined ? 1 : 0), + lPush: async (k: string, v: string) => { + if (!ls()[k]) ls()[k] = []; + ls()[k].unshift(v); + return ls()[k].length; + }, + lRem: async (k: string, _count: number, v: string) => { + if (!ls()[k]) return 0; + const idx = ls()[k].indexOf(v); + if (idx >= 0) { + ls()[k].splice(idx, 1); + return 1; + } + return 0; + }, + lRange: async (k: string, start: number, end: number) => { + if (!ls()[k]) return []; + if (end === -1) return ls()[k].slice(start); + return ls()[k].slice(start, end + 1); + }, + lPos: async (k: string, v: string) => { + if (!ls()[k]) return null; + const idx = ls()[k].indexOf(v); + return idx >= 0 ? idx : null; + }, + sAdd: async (k: string, ...vals: string[]) => { + if (!ss()[k]) ss()[k] = new Set(); + for (const v of vals) ss()[k].add(v); + return vals.length; + }, + sRem: async (k: string, v: string) => (ss()[k]?.delete(v) ? 1 : 0), + sIsMember: async (k: string, v: string) => ss()[k]?.has(v) ?? false, + sMembers: async (k: string) => (ss()[k] ? [...ss()[k]] : []), + incrBy: async (k: string, n: number) => { + const v = Number.parseInt(kv()[k] || "0") + n; + kv()[k] = String(v); + return v; + }, + watch: async () => {}, + multi: makeMulti, + expire: async () => 1, + setNX: async (k: string, v: string) => { + if (kv()[k]) return false; + kv()[k] = v; + return true; + }, + zScore: async () => null, + zAdd: async () => 1, + zCard: async () => 0, + zRemRangeByRank: async () => 0, + keys: async (pattern: string) => { + const ss = globalThis.__testStore.setStore; + const prefix = pattern.replace("*", ""); + return Object.keys(ss).filter((k) => k.startsWith(prefix)); + }, + type: async (k: string) => { + if (globalThis.__testStore.setStore[k]) return "set"; + if (globalThis.__testStore.listStore[k]) return "list"; + if (globalThis.__testStore.kvStore[k] !== undefined) return "string"; + return "none"; + }, }, - watch: async () => {}, - multi: makeMulti, - expire: async () => 1, - setNX: async (k: string, v: string) => { - if (kv()[k]) return false; - kv()[k] = v; - return true; - }, - zScore: async () => null, - zAdd: async () => 1, - zCard: async () => 0, - zRemRangeByRank: async () => 0, - keys: async (pattern: string) => { - const ss = globalThis.__testStore.setStore; - const prefix = pattern.replace("*", ""); - return Object.keys(ss).filter((k) => k.startsWith(prefix)); + g, + s, + gf, + ga: async () => null, + archive: { lRange: async () => [] }, + }; + }); + + mock.module("$config", () => ({ + default: { + bitcoin: { + host: "localhost", + wallet: "test", + user: "u", + password: "p", + network: "regtest", + port: 18443, }, - type: async (k: string) => { - if (globalThis.__testStore.setStore[k]) return "set"; - if (globalThis.__testStore.listStore[k]) return "list"; - if (globalThis.__testStore.kvStore[k] !== undefined) return "string"; - return "none"; + liquid: { + host: "localhost", + wallet: "test", + user: "u", + password: "p", + btc: "test-asset", + port: 7040, }, + lightning: "/dev/null", + fee: { bitcoin: 0.004, liquid: 0.001, lightning: 0.001 }, + adminpass: "test", + ark: { arkPrivateKey: "0000", arkServerUrl: "http://localhost" }, + nostr: "ws://localhost:7777", + tigerbeetle: { cluster_id: 0n, replica_addresses: ["localhost:3000"] }, + vapid: { pk: "test", sk: "test" }, + support: "[email protected]", + txWebhookSecret: "test", }, - g, s, gf, - ga: async () => null, - archive: { lRange: async () => [] }, - }; -}); - -mock.module("$config", () => ({ - default: { - bitcoin: { host: "localhost", wallet: "test", user: "u", password: "p", network: "regtest", port: 18443 }, - liquid: { host: "localhost", wallet: "test", user: "u", password: "p", btc: "test-asset", port: 7040 }, - lightning: "/dev/null", - fee: { bitcoin: 0.004, liquid: 0.001, lightning: 0.001 }, - adminpass: "test", - ark: { arkPrivateKey: "0000", arkServerUrl: "http://localhost" }, - nostr: "ws://localhost:7777", - tigerbeetle: { cluster_id: 0n, replica_addresses: ["localhost:3000"] }, - vapid: { pk: "test", sk: "test" }, - support: "[email protected]", - txWebhookSecret: "test", - }, -})); - -mock.module("$lib/tb", () => ({ - getBalance: mock(async () => 10_000_000), - getCredit: mock(async () => 0), - tbDebit: mock(async () => 0), - tbCredit: mock(async () => undefined), - tbRefund: mock(async () => undefined), - tbReverse: mock(async () => undefined), - tbConfirm: mock(async () => undefined), - tbSetBalance: mock(async () => undefined), - tbSetPending: mock(async () => undefined), - fundDebit: mock(async () => ({ err: null })), - initTigerBeetle: mock(async () => {}), -})); + })); -mock.module("$lib/ln", () => ({ - default: { - decode: mock(async () => ({ type: "bolt11", amount_msat: 1_000_000, payee: "test-payee" })), - listpeerchannels: mock(async () => ({ channels: [] })), - listpays: mock(async () => ({ pays: [] })), - xpay: mock(async () => ({ amount_sent_msat: 1_000_000, payment_preimage: "preimage-abc" })), - getinfo: mock(async () => ({ id: "our-node-id" })), - listinvoices: mock(async () => ({ invoices: [] })), - listfunds: mock(async () => ({ channels: [] })), - keysend: mock(async () => ({})), - fetchinvoice: mock(async () => ({})), - getroutes: mock(async () => ({ routes: [] })), - sendinvoice: mock(async () => ({})), - }, -})); + mock.module("$lib/tb", () => ({ + getBalance: mock(async () => 10_000_000), + getCredit: mock(async () => 0), + tbDebit: mock(async () => 0), + tbCredit: mock(async () => undefined), + tbRefund: mock(async () => undefined), + tbReverse: mock(async () => undefined), + tbConfirm: mock(async () => undefined), + tbSetBalance: mock(async () => undefined), + tbSetPending: mock(async () => undefined), + fundDebit: mock(async () => ({ err: null })), + initTigerBeetle: mock(async () => {}), + })); -mock.module("$lib/logging", () => ({ l: () => {}, warn: mock(() => {}), err: () => {} })); -mock.module("$lib/notifications", () => ({ notify: () => {}, nwcNotify: () => {} })); -mock.module("$lib/webhooks", () => ({ callWebhook: mock(() => {}) })); -mock.module("$lib/sockets", () => ({ emit: mock(() => {}), sendHeartbeat: () => {} })); -mock.module("$lib/esplora", () => ({ - btcNetwork: { bech32: "bcrt", pubKeyHash: 0x6f, scriptHash: 0xc4, wif: 0xef }, - hdVersions: { private: 0x04358394, public: 0x043587cf }, - getAddressTxs: mock(async (address: string) => { - const txs = globalThis.__testStore.esploraOverride?.addressTxs?.[address]; - return txs || []; - }), - getTxStatus: mock(async (txid: string) => { - const status = globalThis.__testStore.esploraOverride?.txStatus?.[txid]; - return status || { confirmed: false }; - }), - getAddressUtxos: mock(async () => []), - getUtxos: mock(async () => []), - getTxHex: mock(async () => ""), - getTx: mock(async () => ({})), - broadcastTx: mock(async () => ({})), - getFeeEstimates: mock(async () => ({})), - deriveAddress: mock(() => ({ address: "bcrt1qmock" })), - deriveAddresses: mock(() => []), - parseDescriptor: mock(() => ({})), - findLastUsedIndex: mock(async () => -1), -})); -mock.module("$lib/square", () => ({ squarePayment: () => {} })); -mock.module("$lib/nostr", () => ({ - handleZap: async () => {}, publish: async () => {}, - serverPubkey: "m", serverPubkey2: "m", serverSecret: "m", serverSecret2: "m", -})); -mock.module("$lib/mqtt", () => ({ default: { publish: () => {} } })); -mock.module("$lib/ark", () => ({ - getArkAddress: async () => "ark-addr", sendArk: async () => "ark-txid", getArkBalance: async () => 0, verifyArkVtxo: async () => true, -})); -mock.module("$lib/ecash", () => ({ request: async () => ({}) })); -mock.module("$lib/lightning", () => ({ - replay: async () => ({}), fixBolt12: () => {}, listenForLightning: () => {}, -})); -mock.module("$lib/mail", () => ({ mail: async () => {}, templates: {} })); -mock.module("$lib/auth", () => ({ - requirePin: async () => {}, auth: (_r: any, _s: any, n: any) => n(), optional: (_r: any, _s: any, n: any) => n(), admin: (_r: any, _s: any, n: any) => n(), -})); -mock.module("$lib/invoices", () => ({ - generate: mock(async ({ invoice, user }: any) => ({ - id: "gen-inv", hash: "gen-hash", uid: user?.id, received: 0, pending: 0, ...invoice, - })), -})); -mock.module("$lib/api", () => ({ default: { bitcoin: "http://localhost", liquid: "http://localhost" } })); -mock.module("$lib/store", () => ({ default: { rates: { USD: 50000 } } })); -mock.module("@coinos/rpc", () => ({ - default: () => new Proxy({}, { - get: (_target, prop) => async (...args: any[]) => { - const override = globalThis.__testStore.rpcOverride; - if (override && typeof override[prop] === "function") { - return override[prop](...args); - } - return {}; + mock.module("$lib/ln", () => ({ + default: { + decode: mock(async () => ({ type: "bolt11", amount_msat: 1_000_000, payee: "test-payee" })), + listpeerchannels: mock(async () => ({ channels: [] })), + listpays: mock(async () => ({ pays: [] })), + xpay: mock(async () => ({ amount_sent_msat: 1_000_000, payment_preimage: "preimage-abc" })), + getinfo: mock(async () => ({ id: "our-node-id" })), + listinvoices: mock(async () => ({ invoices: [] })), + listfunds: mock(async () => ({ channels: [] })), + keysend: mock(async () => ({})), + fetchinvoice: mock(async () => ({})), + getroutes: mock(async () => ({ routes: [] })), + sendinvoice: mock(async () => ({})), }, - }), -})); + })); -mock.module("$lib/utils", () => { - const SATS = 100_000_000; - const kv = () => globalThis.__testStore.kvStore; - return { - SATS, - btc: (n: number) => Number.parseFloat((n / SATS).toFixed(8)), - fail: (msg: string) => { throw new Error(msg); }, - fmt: (n: number) => String(n), - formatReceipt: () => {}, - getInvoice: async (hash: string) => { - const raw = kv()[`invoice:${hash}`] ?? null; - if (!raw) return null; - let iid; - try { iid = JSON.parse(raw); } catch { iid = raw; } - if (iid?.id) iid = iid.id; - else if (iid?.hash) iid = iid.hash; - const raw2 = kv()[`invoice:${iid}`] ?? null; - if (!raw2) return null; - try { return JSON.parse(raw2); } catch { return raw2; } - }, - getPayment: async (id: string) => { - const raw = kv()[`payment:${id}`]; - if (!raw) return null; - try { - const parsed = JSON.parse(raw); - if (typeof parsed === "string") { - const p = kv()[`payment:${parsed}`]; - return p ? JSON.parse(p) : null; - } - return parsed; - } catch { return null; } - }, - getUser: async (username: string) => { - const raw = kv()[`user:${username}`]; - return raw ? JSON.parse(raw) : null; - }, - getAccount: async () => null, - link: (id: string) => `http://test/${id}`, - sats: (n: number) => Math.round(n * SATS), - sleep: async () => {}, - t: () => ({ insufficientFunds: "Insufficient funds" }), - bail: (res: any, msg: string) => res.code(500).send(msg), - bip21: () => "", - fields: [], - nada: () => {}, - fiat: (n: number, r: number) => (n * r) / SATS, - f: (s: any) => String(s), - pick: (O: any, K: string[]) => K.reduce((o: any, k: string) => ((o[k] = O[k]), o), {}), - prod: false, - uniq: (a: any[], k: any) => [...new Map(a.map((x: any) => [k(x), x])).values()], - wait: async () => {}, - time: () => ({ start: () => {}, end: () => {} }), - }; -}); + mock.module("$lib/logging", () => ({ l: () => {}, warn: mock(() => {}), err: () => {} })); + mock.module("$lib/notifications", () => ({ notify: () => {}, nwcNotify: () => {} })); + mock.module("$lib/webhooks", () => ({ callWebhook: mock(() => {}) })); + mock.module("$lib/sockets", () => ({ emit: mock(() => {}), sendHeartbeat: () => {} })); + mock.module("$lib/esplora", () => ({ + btcNetwork: { bech32: "bcrt", pubKeyHash: 0x6f, scriptHash: 0xc4, wif: 0xef }, + hdVersions: { private: 0x04358394, public: 0x043587cf }, + getAddressTxs: mock(async (address: string) => { + const txs = globalThis.__testStore.esploraOverride?.addressTxs?.[address]; + return txs || []; + }), + getTxStatus: mock(async (txid: string) => { + const status = globalThis.__testStore.esploraOverride?.txStatus?.[txid]; + return status || { confirmed: false }; + }), + getAddressUtxos: mock(async () => []), + getUtxos: mock(async () => []), + getTxHex: mock(async () => ""), + getTx: mock(async () => ({})), + broadcastTx: mock(async () => ({})), + getFeeEstimates: mock(async () => ({})), + deriveAddress: mock(() => ({ address: "bcrt1qmock" })), + deriveAddresses: mock(() => []), + parseDescriptor: mock(() => ({})), + findLastUsedIndex: mock(async () => -1), + })); + mock.module("$lib/square", () => ({ squarePayment: () => {} })); + mock.module("$lib/nostr", () => ({ + handleZap: async () => {}, + publish: async () => {}, + serverPubkey: "m", + serverPubkey2: "m", + serverSecret: "m", + serverSecret2: "m", + })); + mock.module("$lib/mqtt", () => ({ default: { publish: () => {} } })); + mock.module("$lib/ark", () => ({ + getArkAddress: async () => "ark-addr", + sendArk: async () => "ark-txid", + getArkBalance: async () => 0, + verifyArkVtxo: async () => true, + })); + mock.module("$lib/ecash", () => ({ request: async () => ({}) })); + mock.module("$lib/lightning", () => ({ + replay: async () => ({}), + fixBolt12: () => {}, + listenForLightning: () => {}, + })); + mock.module("$lib/mail", () => ({ mail: async () => {}, templates: {} })); + mock.module("$lib/auth", () => ({ + requirePin: async () => {}, + auth: (_r: any, _s: any, n: any) => n(), + optional: (_r: any, _s: any, n: any) => n(), + admin: (_r: any, _s: any, n: any) => n(), + })); + mock.module("$lib/invoices", () => ({ + generate: mock(async ({ invoice, user }: any) => ({ + id: "gen-inv", + hash: "gen-hash", + uid: user?.id, + received: 0, + pending: 0, + ...invoice, + })), + })); + mock.module("$lib/api", () => ({ + default: { bitcoin: "http://localhost", liquid: "http://localhost" }, + })); + mock.module("$lib/store", () => ({ default: { rates: { USD: 50000 } } })); + mock.module("@coinos/rpc", () => ({ + default: () => + new Proxy( + {}, + { + get: + (_target, prop) => + async (...args: any[]) => { + const override = globalThis.__testStore.rpcOverride; + if (override && typeof override[prop] === "function") { + return override[prop](...args); + } + return {}; + }, + }, + ), + })); + mock.module("$lib/utils", () => { + const SATS = 100_000_000; + const kv = () => globalThis.__testStore.kvStore; + return { + SATS, + btc: (n: number) => Number.parseFloat((n / SATS).toFixed(8)), + fail: (msg: string) => { + throw new Error(msg); + }, + fmt: (n: number) => String(n), + formatReceipt: () => {}, + getInvoice: async (hash: string) => { + const raw = kv()[`invoice:${hash}`] ?? null; + if (!raw) return null; + let iid; + try { + iid = JSON.parse(raw); + } catch { + iid = raw; + } + if (iid?.id) iid = iid.id; + else if (iid?.hash) iid = iid.hash; + const raw2 = kv()[`invoice:${iid}`] ?? null; + if (!raw2) return null; + try { + return JSON.parse(raw2); + } catch { + return raw2; + } + }, + getPayment: async (id: string) => { + const raw = kv()[`payment:${id}`]; + if (!raw) return null; + try { + const parsed = JSON.parse(raw); + if (typeof parsed === "string") { + const p = kv()[`payment:${parsed}`]; + return p ? JSON.parse(p) : null; + } + return parsed; + } catch { + return null; + } + }, + getUser: async (username: string) => { + const raw = kv()[`user:${username}`]; + return raw ? JSON.parse(raw) : null; + }, + getAccount: async () => null, + link: (id: string) => `http://test/${id}`, + sats: (n: number) => Math.round(n * SATS), + sleep: async () => {}, + t: () => ({ insufficientFunds: "Insufficient funds" }), + bail: (res: any, msg: string) => res.code(500).send(msg), + bip21: () => "", + fields: [], + nada: () => {}, + fiat: (n: number, r: number) => (n * r) / SATS, + f: (s: any) => String(s), + pick: (O: any, K: string[]) => K.reduce((o: any, k: string) => ((o[k] = O[k]), o), {}), + prod: false, + uniq: (a: any[], k: any) => [...new Map(a.map((x: any) => [k(x), x])).values()], + wait: async () => {}, + time: () => ({ start: () => {}, end: () => {} }), + }; + }); } // end INTEGRATION skip |
