From ad967bbb5d57c03b567f1964db7a4462831dc08b Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 14 Feb 2025 10:46:59 -0300 Subject: [PATCH 1/6] Revert "Delete cashu.test.ts" This reverts commit 032b29cfbac6d244bbab663d20665b3568050997. --- src/controllers/api/cashu.test.ts | 297 ++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/controllers/api/cashu.test.ts diff --git a/src/controllers/api/cashu.test.ts b/src/controllers/api/cashu.test.ts new file mode 100644 index 00000000..ac8eb699 --- /dev/null +++ b/src/controllers/api/cashu.test.ts @@ -0,0 +1,297 @@ +import { Env as HonoEnv, Hono } from '@hono/hono'; +import { NostrSigner, NSecSigner, NStore } from '@nostrify/nostrify'; +import { generateSecretKey, getPublicKey } from 'nostr-tools'; +import { bytesToString, stringToBytes } from '@scure/base'; +import { assertEquals, assertExists, assertObjectMatch } from '@std/assert'; + +import { createTestDB, genEvent } from '@/test.ts'; + +import cashuApp from '@/controllers/api/cashu.ts'; +import { walletSchema } from '@/schema.ts'; + +interface AppEnv extends HonoEnv { + Variables: { + /** Signer to get the logged-in user's pubkey, relays, and to sign events. */ + signer: NostrSigner; + /** Storage for the user, might filter out unwanted content. */ + store: NStore; + }; +} + +Deno.test('PUT /wallet must be successful', { + sanitizeOps: false, + sanitizeResources: false, +}, async () => { + await using db = await createTestDB(); + const store = db.store; + + const sk = generateSecretKey(); + const signer = new NSecSigner(sk); + const nostrPrivateKey = bytesToString('hex', sk); + + const app = new Hono().use( + async (c, next) => { + c.set('signer', signer); + await next(); + }, + async (c, next) => { + c.set('store', store); + await next(); + }, + ).route('/', cashuApp); + + const response = await app.request('/wallet', { + method: 'PUT', + headers: [['content-type', 'application/json']], + body: JSON.stringify({ + mints: [ + 'https://houston.mint.com', + 'https://houston.mint.com', // duplicate on purpose + 'https://cuiaba.mint.com', + ], + }), + }); + + assertEquals(response.status, 200); + + const pubkey = await signer.getPublicKey(); + + const [wallet] = await store.query([{ authors: [pubkey], kinds: [17375] }]); + + assertExists(wallet); + assertEquals(wallet.kind, 17375); + + const { data, success } = walletSchema.safeParse(await response.json()); + + assertEquals(success, true); + if (!data) return; // get rid of typescript error possibly undefined + + const decryptedContent: string[][] = JSON.parse(await signer.nip44.decrypt(pubkey, wallet.content)); + + const privkey = decryptedContent.find(([value]) => value === 'privkey')?.[1]!; + const p2pk = getPublicKey(stringToBytes('hex', privkey)); + + assertEquals(nostrPrivateKey !== privkey, true); + + assertEquals(data.pubkey_p2pk, p2pk); + assertEquals(data.mints, [ + 'https://houston.mint.com', + 'https://cuiaba.mint.com', + ]); + assertEquals(data.relays, [ + 'ws://localhost:4036/relay', + ]); + assertEquals(data.balance, 0); + + const [nutzap_info] = await store.query([{ authors: [pubkey], kinds: [10019] }]); + + assertExists(nutzap_info); + assertEquals(nutzap_info.kind, 10019); + assertEquals(nutzap_info.tags.length, 4); + + const nutzap_p2pk = nutzap_info.tags.find(([value]) => value === 'pubkey')?.[1]!; + + assertEquals(nutzap_p2pk, p2pk); + assertEquals([nutzap_info.tags.find(([name]) => name === 'relay')?.[1]!], [ + 'ws://localhost:4036/relay', + ]); +}); + +Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', async () => { + await using db = await createTestDB(); + const store = db.store; + + const sk = generateSecretKey(); + const signer = new NSecSigner(sk); + + const app = new Hono().use( + async (c, next) => { + c.set('signer', signer); + await next(); + }, + async (c, next) => { + c.set('store', store); + await next(); + }, + ).route('/', cashuApp); + + const response = await app.request('/wallet', { + method: 'PUT', + headers: [['content-type', 'application/json']], + body: JSON.stringify({ + mints: [], // no mints should throw an error + }), + }); + + const body = await response.json(); + + assertEquals(response.status, 400); + assertObjectMatch(body, { error: 'Bad schema' }); +}); + +Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () => { + await using db = await createTestDB(); + const store = db.store; + + const sk = generateSecretKey(); + const signer = new NSecSigner(sk); + + const app = new Hono().use( + async (c, next) => { + c.set('signer', signer); + await next(); + }, + async (c, next) => { + c.set('store', store); + await next(); + }, + ).route('/', cashuApp); + + await db.store.event(genEvent({ kind: 17375 }, sk)); + + const response = await app.request('/wallet', { + method: 'PUT', + headers: [['content-type', 'application/json']], + body: JSON.stringify({ + mints: ['https://mint.heart.com'], + }), + }); + + const body2 = await response.json(); + + assertEquals(response.status, 400); + assertEquals(body2, { error: 'You already have a wallet 😏' }); +}); + +Deno.test('GET /wallet must be successful', async () => { + await using db = await createTestDB(); + const store = db.store; + + const sk = generateSecretKey(); + const signer = new NSecSigner(sk); + const pubkey = await signer.getPublicKey(); + const privkey = bytesToString('hex', sk); + const p2pk = getPublicKey(stringToBytes('hex', privkey)); + + const app = new Hono().use( + async (c, next) => { + c.set('signer', signer); + await next(); + }, + async (c, next) => { + c.set('store', store); + await next(); + }, + ).route('/', cashuApp); + + // Wallet + await db.store.event(genEvent({ + kind: 17375, + content: await signer.nip44.encrypt( + pubkey, + JSON.stringify([ + ['privkey', privkey], + ['mint', 'https://mint.soul.com'], + ]), + ), + }, sk)); + + // Nutzap information + await db.store.event(genEvent({ + kind: 10019, + tags: [ + ['pubkey', p2pk], + ['mint', 'https://mint.soul.com'], + ], + }, sk)); + + // Unspent proofs + await db.store.event(genEvent({ + kind: 7375, + content: await signer.nip44.encrypt( + pubkey, + JSON.stringify({ + mint: 'https://mint.soul.com', + proofs: [ + { + id: '005c2502034d4f12', + amount: 25, + secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=', + C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46', + }, + { + id: '005c2502034d4f12', + amount: 25, + secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=', + C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46', + }, + { + id: '005c2502034d4f12', + amount: 25, + secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=', + C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46', + }, + { + id: '005c2502034d4f12', + amount: 25, + secret: 'z+zyxAVLRqN9lEjxuNPSyRJzEstbl69Jc1vtimvtkPg=', + C: '0241d98a8197ef238a192d47edf191a9de78b657308937b4f7dd0aa53beae72c46', + }, + ], + del: [], + }), + ), + }, sk)); + + // TODO: find a way to have a Mock mint so operations like 'swap', 'mint' and 'melt' can be tested (this will be a bit hard). + // Nutzap + const senderSk = generateSecretKey(); + + await db.store.event(genEvent({ + kind: 9321, + content: 'Nice post!', + tags: [ + ['p', pubkey], + ['u', 'https://mint.soul.com'], + [ + 'proof', + '{"amount":1,"C":"02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f","id":"000a93d6f8a1d2c4","secret":"[\\"P2PK\\",{\\"nonce\\":\\"b00bdd0467b0090a25bdf2d2f0d45ac4e355c482c1418350f273a04fedaaee83\\",\\"data\\":\\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\\"}]"}', + ], + ], + }, senderSk)); + + const response = await app.request('/wallet', { + method: 'GET', + }); + + const body = await response.json(); + + assertEquals(response.status, 200); + assertEquals(body, { + pubkey_p2pk: p2pk, + mints: ['https://mint.soul.com'], + relays: ['ws://localhost:4036/relay'], + balance: 100, + }); +}); + +Deno.test('GET /mints must be successful', async () => { + await using db = await createTestDB(); + const store = db.store; + + const app = new Hono().use( + async (c, next) => { + c.set('store', store); + await next(); + }, + ).route('/', cashuApp); + + const response = await app.request('/mints', { + method: 'GET', + }); + + const body = await response.json(); + + assertEquals(response.status, 200); + assertEquals(body, { mints: [] }); +}); From 461feff952017c354084b8efd19267015bcd50ac Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 14 Feb 2025 11:28:10 -0300 Subject: [PATCH 2/6] fix: make cashu tests faster by giving invalid URL --- src/controllers/api/cashu.test.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/controllers/api/cashu.test.ts b/src/controllers/api/cashu.test.ts index ac8eb699..7bdb801d 100644 --- a/src/controllers/api/cashu.test.ts +++ b/src/controllers/api/cashu.test.ts @@ -45,9 +45,9 @@ Deno.test('PUT /wallet must be successful', { headers: [['content-type', 'application/json']], body: JSON.stringify({ mints: [ - 'https://houston.mint.com', - 'https://houston.mint.com', // duplicate on purpose - 'https://cuiaba.mint.com', + 'ditto://houston.mint.com', + 'ditto://houston.mint.com', // duplicate on purpose + 'ditto://cuiaba.mint.com', ], }), }); @@ -75,8 +75,8 @@ Deno.test('PUT /wallet must be successful', { assertEquals(data.pubkey_p2pk, p2pk); assertEquals(data.mints, [ - 'https://houston.mint.com', - 'https://cuiaba.mint.com', + 'ditto://houston.mint.com', + 'ditto://cuiaba.mint.com', ]); assertEquals(data.relays, [ 'ws://localhost:4036/relay', @@ -153,7 +153,7 @@ Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () method: 'PUT', headers: [['content-type', 'application/json']], body: JSON.stringify({ - mints: ['https://mint.heart.com'], + mints: ['ditto://mint.heart.com'], }), }); @@ -191,7 +191,7 @@ Deno.test('GET /wallet must be successful', async () => { pubkey, JSON.stringify([ ['privkey', privkey], - ['mint', 'https://mint.soul.com'], + ['mint', 'ditto://mint.soul.com'], ]), ), }, sk)); @@ -201,7 +201,7 @@ Deno.test('GET /wallet must be successful', async () => { kind: 10019, tags: [ ['pubkey', p2pk], - ['mint', 'https://mint.soul.com'], + ['mint', 'ditto://mint.soul.com'], ], }, sk)); @@ -211,7 +211,7 @@ Deno.test('GET /wallet must be successful', async () => { content: await signer.nip44.encrypt( pubkey, JSON.stringify({ - mint: 'https://mint.soul.com', + mint: 'ditto://mint.soul.com', proofs: [ { id: '005c2502034d4f12', @@ -252,7 +252,7 @@ Deno.test('GET /wallet must be successful', async () => { content: 'Nice post!', tags: [ ['p', pubkey], - ['u', 'https://mint.soul.com'], + ['u', 'ditto://mint.soul.com'], [ 'proof', '{"amount":1,"C":"02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f","id":"000a93d6f8a1d2c4","secret":"[\\"P2PK\\",{\\"nonce\\":\\"b00bdd0467b0090a25bdf2d2f0d45ac4e355c482c1418350f273a04fedaaee83\\",\\"data\\":\\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\\"}]"}', @@ -269,7 +269,7 @@ Deno.test('GET /wallet must be successful', async () => { assertEquals(response.status, 200); assertEquals(body, { pubkey_p2pk: p2pk, - mints: ['https://mint.soul.com'], + mints: ['ditto://mint.soul.com'], relays: ['ws://localhost:4036/relay'], balance: 100, }); From 9e7576f248036b8c075060c21971fe34566aec94 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 14 Feb 2025 11:33:14 -0300 Subject: [PATCH 3/6] deno.lock: types/node --- deno.lock | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/deno.lock b/deno.lock index e4e2e2c3..58823763 100644 --- a/deno.lock +++ b/deno.lock @@ -93,6 +93,7 @@ "npm:@scure/base@^1.1.6": "1.1.6", "npm:@scure/bip32@^1.4.0": "1.4.0", "npm:@scure/bip39@^1.3.0": "1.3.0", + "npm:@types/node@*": "22.5.4", "npm:blurhash@2.0.5": "2.0.5", "npm:comlink-async-generator@*": "0.0.1", "npm:comlink-async-generator@^0.0.1": "0.0.1", @@ -959,6 +960,12 @@ "@types/trusted-types" ] }, + "@types/node@22.5.4": { + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": [ + "undici-types" + ] + }, "@types/trusted-types@2.0.7": { "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, @@ -1720,6 +1727,9 @@ "type-fest@4.18.2": { "integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==" }, + "undici-types@6.19.8": { + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, "unfurl.js@6.4.0": { "integrity": "sha512-DogJFWPkOWMcu2xPdpmbcsL+diOOJInD3/jXOv6saX1upnWmMK8ndAtDWUfJkuInqNI9yzADud4ID9T+9UeWCw==", "dependencies": [ From cb475f11261ccc2f27880abb321eb1d9c70ce2cd Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 14 Feb 2025 11:51:36 -0300 Subject: [PATCH 4/6] dependency: add jsr:@std/testing/mock --- deno.json | 1 + deno.lock | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/deno.json b/deno.json index c11f038b..c735663d 100644 --- a/deno.json +++ b/deno.json @@ -66,6 +66,7 @@ "@std/json": "jsr:@std/json@^0.223.0", "@std/media-types": "jsr:@std/media-types@^0.224.1", "@std/streams": "jsr:@std/streams@^0.223.0", + "@std/testing": "jsr:@std/testing@^1.0.9", "blurhash": "npm:blurhash@2.0.5", "comlink": "npm:comlink@^4.4.1", "comlink-async-generator": "npm:comlink-async-generator@^0.0.1", diff --git a/deno.lock b/deno.lock index 58823763..b46ce6da 100644 --- a/deno.lock +++ b/deno.lock @@ -55,6 +55,7 @@ "jsr:@soapbox/safe-fetch@2": "2.0.0", "jsr:@std/assert@0.223": "0.223.0", "jsr:@std/assert@0.224": "0.224.0", + "jsr:@std/assert@^1.0.10": "1.0.11", "jsr:@std/assert@~0.213.1": "0.213.1", "jsr:@std/assert@~0.225.1": "0.225.3", "jsr:@std/bytes@0.223": "0.223.0", @@ -66,6 +67,7 @@ "jsr:@std/bytes@^1.0.2-rc.3": "1.0.2", "jsr:@std/cli@0.223": "0.223.0", "jsr:@std/crypto@0.224": "0.224.0", + "jsr:@std/data-structures@^1.0.6": "1.0.6", "jsr:@std/encoding@0.213.1": "0.213.1", "jsr:@std/encoding@0.224": "0.224.3", "jsr:@std/encoding@0.224.0": "0.224.0", @@ -73,8 +75,10 @@ "jsr:@std/encoding@~0.224.1": "0.224.3", "jsr:@std/fmt@0.213.1": "0.213.1", "jsr:@std/fs@0.213.1": "0.213.1", + "jsr:@std/fs@^1.0.9": "1.0.11", "jsr:@std/fs@~0.229.3": "0.229.3", "jsr:@std/internal@1": "1.0.5", + "jsr:@std/internal@^1.0.5": "1.0.5", "jsr:@std/io@0.223": "0.223.0", "jsr:@std/io@0.224": "0.224.9", "jsr:@std/json@0.223": "0.223.0", @@ -83,8 +87,10 @@ "jsr:@std/path@0.213.1": "0.213.1", "jsr:@std/path@0.224.0": "0.224.0", "jsr:@std/path@1.0.0-rc.1": "1.0.0-rc.1", + "jsr:@std/path@^1.0.8": "1.0.8", "jsr:@std/path@~0.213.1": "0.213.1", "jsr:@std/streams@0.223": "0.223.0", + "jsr:@std/testing@^1.0.9": "1.0.9", "npm:@cashu/cashu-ts@^2.2.0": "2.2.0", "npm:@electric-sql/pglite@~0.2.8": "0.2.8", "npm:@isaacs/ttlcache@^1.4.1": "1.4.1", @@ -571,7 +577,13 @@ "@std/assert@0.225.3": { "integrity": "b3c2847aecf6955b50644cdb9cf072004ea3d1998dd7579fc0acb99dbb23bd4f", "dependencies": [ - "jsr:@std/internal" + "jsr:@std/internal@1" + ] + }, + "@std/assert@1.0.11": { + "integrity": "2461ef3c368fe88bc60e186e7744a93112f16fd110022e113a0849e94d1c83c1", + "dependencies": [ + "jsr:@std/internal@^1.0.5" ] }, "@std/bytes@0.223.0": { @@ -602,6 +614,9 @@ "jsr:@std/encoding@0.224" ] }, + "@std/data-structures@1.0.6": { + "integrity": "76a7fd8080c66604c0496220a791860492ab21a04a63a969c0b9a0609bbbb760" + }, "@std/dotenv@0.224.0": { "integrity": "d9234cdf551507dcda60abb6c474289843741d8c07ee8ce540c60f5c1b220a1d" }, @@ -633,6 +648,12 @@ "jsr:@std/path@1.0.0-rc.1" ] }, + "@std/fs@1.0.11": { + "integrity": "ba674672693340c5ebdd018b4fe1af46cb08741f42b4c538154e97d217b55bdd", + "dependencies": [ + "jsr:@std/path@^1.0.8" + ] + }, "@std/internal@1.0.0": { "integrity": "ac6a6dfebf838582c4b4f61a6907374e27e05bedb6ce276e0f1608fe84e7cd9a" }, @@ -730,6 +751,9 @@ "@std/path@1.0.0-rc.1": { "integrity": "b8c00ae2f19106a6bb7cbf1ab9be52aa70de1605daeb2dbdc4f87a7cbaf10ff6" }, + "@std/path@1.0.8": { + "integrity": "548fa456bb6a04d3c1a1e7477986b6cffbce95102d0bb447c67c4ee70e0364be" + }, "@std/streams@0.223.0": { "integrity": "d6b28e498ced3960b04dc5d251f2dcfc1df244b5ec5a48dc23a8f9b490be3b99", "dependencies": [ @@ -737,6 +761,16 @@ "jsr:@std/bytes@0.223", "jsr:@std/io@0.223" ] + }, + "@std/testing@1.0.9": { + "integrity": "9bdd4ac07cb13e7594ac30e90f6ceef7254ac83a9aeaa089be0008f33aab5cd4", + "dependencies": [ + "jsr:@std/assert@^1.0.10", + "jsr:@std/data-structures", + "jsr:@std/fs@^1.0.9", + "jsr:@std/internal@^1.0.5", + "jsr:@std/path@^1.0.8" + ] } }, "npm": { @@ -2441,6 +2475,7 @@ "jsr:@std/json@0.223", "jsr:@std/media-types@~0.224.1", "jsr:@std/streams@0.223", + "jsr:@std/testing@^1.0.9", "npm:@cashu/cashu-ts@^2.2.0", "npm:@electric-sql/pglite@~0.2.8", "npm:@isaacs/ttlcache@^1.4.1", From 028d41d585b3df896a96b0efc61b85ae5e48d135 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 14 Feb 2025 11:52:37 -0300 Subject: [PATCH 5/6] refactor: use fetch mock --- src/controllers/api/cashu.test.ts | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/controllers/api/cashu.test.ts b/src/controllers/api/cashu.test.ts index 7bdb801d..3f53bb10 100644 --- a/src/controllers/api/cashu.test.ts +++ b/src/controllers/api/cashu.test.ts @@ -9,6 +9,12 @@ import { createTestDB, genEvent } from '@/test.ts'; import cashuApp from '@/controllers/api/cashu.ts'; import { walletSchema } from '@/schema.ts'; +import { stub } from '@std/testing/mock'; + +stub(globalThis, 'fetch', () => { + return Promise.resolve(new Response()); +}); + interface AppEnv extends HonoEnv { Variables: { /** Signer to get the logged-in user's pubkey, relays, and to sign events. */ @@ -45,9 +51,9 @@ Deno.test('PUT /wallet must be successful', { headers: [['content-type', 'application/json']], body: JSON.stringify({ mints: [ - 'ditto://houston.mint.com', - 'ditto://houston.mint.com', // duplicate on purpose - 'ditto://cuiaba.mint.com', + 'https://houston.mint.com', + 'https://houston.mint.com', // duplicate on purpose + 'https://cuiaba.mint.com', ], }), }); @@ -75,8 +81,8 @@ Deno.test('PUT /wallet must be successful', { assertEquals(data.pubkey_p2pk, p2pk); assertEquals(data.mints, [ - 'ditto://houston.mint.com', - 'ditto://cuiaba.mint.com', + 'https://houston.mint.com', + 'https://cuiaba.mint.com', ]); assertEquals(data.relays, [ 'ws://localhost:4036/relay', @@ -153,7 +159,7 @@ Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () method: 'PUT', headers: [['content-type', 'application/json']], body: JSON.stringify({ - mints: ['ditto://mint.heart.com'], + mints: ['https://mint.heart.com'], }), }); @@ -191,7 +197,7 @@ Deno.test('GET /wallet must be successful', async () => { pubkey, JSON.stringify([ ['privkey', privkey], - ['mint', 'ditto://mint.soul.com'], + ['mint', 'https://mint.soul.com'], ]), ), }, sk)); @@ -201,7 +207,7 @@ Deno.test('GET /wallet must be successful', async () => { kind: 10019, tags: [ ['pubkey', p2pk], - ['mint', 'ditto://mint.soul.com'], + ['mint', 'https://mint.soul.com'], ], }, sk)); @@ -211,7 +217,7 @@ Deno.test('GET /wallet must be successful', async () => { content: await signer.nip44.encrypt( pubkey, JSON.stringify({ - mint: 'ditto://mint.soul.com', + mint: 'https://mint.soul.com', proofs: [ { id: '005c2502034d4f12', @@ -252,7 +258,7 @@ Deno.test('GET /wallet must be successful', async () => { content: 'Nice post!', tags: [ ['p', pubkey], - ['u', 'ditto://mint.soul.com'], + ['u', 'https://mint.soul.com'], [ 'proof', '{"amount":1,"C":"02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f","id":"000a93d6f8a1d2c4","secret":"[\\"P2PK\\",{\\"nonce\\":\\"b00bdd0467b0090a25bdf2d2f0d45ac4e355c482c1418350f273a04fedaaee83\\",\\"data\\":\\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\\"}]"}', @@ -269,7 +275,7 @@ Deno.test('GET /wallet must be successful', async () => { assertEquals(response.status, 200); assertEquals(body, { pubkey_p2pk: p2pk, - mints: ['ditto://mint.soul.com'], + mints: ['https://mint.soul.com'], relays: ['ws://localhost:4036/relay'], balance: 100, }); From 31eb74b6e4a9bf3df1f3e85587381dc6e1c5d837 Mon Sep 17 00:00:00 2001 From: "P. Reis" Date: Fri, 14 Feb 2025 14:47:20 -0300 Subject: [PATCH 6/6] refactor: use mockFetch --- src/controllers/api/cashu.test.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/controllers/api/cashu.test.ts b/src/controllers/api/cashu.test.ts index 3f53bb10..5aaa772c 100644 --- a/src/controllers/api/cashu.test.ts +++ b/src/controllers/api/cashu.test.ts @@ -2,6 +2,7 @@ import { Env as HonoEnv, Hono } from '@hono/hono'; import { NostrSigner, NSecSigner, NStore } from '@nostrify/nostrify'; import { generateSecretKey, getPublicKey } from 'nostr-tools'; import { bytesToString, stringToBytes } from '@scure/base'; +import { stub } from '@std/testing/mock'; import { assertEquals, assertExists, assertObjectMatch } from '@std/assert'; import { createTestDB, genEvent } from '@/test.ts'; @@ -9,12 +10,6 @@ import { createTestDB, genEvent } from '@/test.ts'; import cashuApp from '@/controllers/api/cashu.ts'; import { walletSchema } from '@/schema.ts'; -import { stub } from '@std/testing/mock'; - -stub(globalThis, 'fetch', () => { - return Promise.resolve(new Response()); -}); - interface AppEnv extends HonoEnv { Variables: { /** Signer to get the logged-in user's pubkey, relays, and to sign events. */ @@ -28,6 +23,7 @@ Deno.test('PUT /wallet must be successful', { sanitizeOps: false, sanitizeResources: false, }, async () => { + using _mock = mockFetch(); await using db = await createTestDB(); const store = db.store; @@ -104,6 +100,7 @@ Deno.test('PUT /wallet must be successful', { }); Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', async () => { + using _mock = mockFetch(); await using db = await createTestDB(); const store = db.store; @@ -136,6 +133,7 @@ Deno.test('PUT /wallet must NOT be successful: wrong request body/schema', async }); Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () => { + using _mock = mockFetch(); await using db = await createTestDB(); const store = db.store; @@ -170,6 +168,7 @@ Deno.test('PUT /wallet must NOT be successful: wallet already exists', async () }); Deno.test('GET /wallet must be successful', async () => { + using _mock = mockFetch(); await using db = await createTestDB(); const store = db.store; @@ -282,6 +281,7 @@ Deno.test('GET /wallet must be successful', async () => { }); Deno.test('GET /mints must be successful', async () => { + using _mock = mockFetch(); await using db = await createTestDB(); const store = db.store; @@ -301,3 +301,14 @@ Deno.test('GET /mints must be successful', async () => { assertEquals(response.status, 200); assertEquals(body, { mints: [] }); }); + +function mockFetch() { + const mock = stub(globalThis, 'fetch', () => { + return Promise.resolve(new Response()); + }); + return { + [Symbol.dispose]: () => { + mock.restore(); + }, + }; +}