More tests
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
import {describe, it, expect, vi, beforeEach, afterEach} from "vitest"
|
||||
import {ctx, fetchJson, bech32ToHex, hexToBech32, tryCatch, postJson} from "@welshman/lib"
|
||||
import {fetchZappers} from "../src/zappers.ts"
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock("@welshman/lib", async imports => {
|
||||
return {
|
||||
...(await imports()),
|
||||
ctx: {
|
||||
app: {
|
||||
dufflepudUrl: undefined, // Will be modified in tests
|
||||
},
|
||||
},
|
||||
identity: x => x,
|
||||
fetchJson: vi.fn(),
|
||||
bech32ToHex: vi.fn(),
|
||||
hexToBech32: vi.fn(),
|
||||
tryCatch: vi.fn(fn => {
|
||||
try {
|
||||
return fn()
|
||||
} catch (e) {
|
||||
return undefined
|
||||
}
|
||||
}),
|
||||
postJson: vi.fn(),
|
||||
}
|
||||
})
|
||||
|
||||
describe("fetchZappers", () => {
|
||||
const mockLnurls = [
|
||||
"lnurl1dp68gurn8ghj7um5v93kketj9ehx2amn9uh8wetvdskkkmn0wahz7mrww4excup0d3h82unvwqhkxctvd46820w0fjx",
|
||||
"lnurl2wd68gurn8ghj7ur5v9kxjerrv9kzum5v93kket39ehx7mmwp5hxsmwda8hx",
|
||||
]
|
||||
|
||||
const mockHexLnurls = ["41414141414141", "42424242424242"]
|
||||
|
||||
const mockZapperInfo1 = {
|
||||
callback: "https://zapper1.com/callback",
|
||||
minSendable: 1000,
|
||||
maxSendable: 100000000,
|
||||
metadata: JSON.stringify([["text/plain", "Zapper One"]]),
|
||||
}
|
||||
|
||||
const mockZapperInfo2 = {
|
||||
callback: "https://zapper2.com/callback",
|
||||
minSendable: 2000,
|
||||
maxSendable: 200000000,
|
||||
metadata: JSON.stringify([["text/plain", "Zapper Two"]]),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
// Default bech32ToHex mockup with 1:1 mapping to hexes
|
||||
vi.mocked(bech32ToHex).mockImplementation(lnurl => {
|
||||
if (lnurl === mockLnurls[0]) return mockHexLnurls[0]
|
||||
if (lnurl === mockLnurls[1]) return mockHexLnurls[1]
|
||||
throw new Error("Invalid lnurl")
|
||||
})
|
||||
|
||||
// Default hexToBech32 mockup with inverse mapping
|
||||
vi.mocked(hexToBech32).mockImplementation((prefix, hex) => {
|
||||
if (hex === mockHexLnurls[0]) return mockLnurls[0]
|
||||
if (hex === mockHexLnurls[1]) return mockLnurls[1]
|
||||
throw new Error("Invalid hex")
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.resetAllMocks()
|
||||
})
|
||||
|
||||
it("should fetch zappers using dufflepud when URL is provided", async () => {
|
||||
// Arrange
|
||||
const dufflepudUrl = "https://dufflepud.com"
|
||||
ctx.app.dufflepudUrl = dufflepudUrl
|
||||
|
||||
vi.mocked(postJson).mockResolvedValue({
|
||||
data: [
|
||||
{lnurl: mockHexLnurls[0], info: mockZapperInfo1},
|
||||
{lnurl: mockHexLnurls[1], info: mockZapperInfo2},
|
||||
],
|
||||
})
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers(mockLnurls)
|
||||
|
||||
// Assert
|
||||
expect(postJson).toHaveBeenCalledWith(`${dufflepudUrl}/zapper/info`, {lnurls: mockHexLnurls})
|
||||
|
||||
expect(bech32ToHex).toHaveBeenCalledTimes(2)
|
||||
expect(hexToBech32).toHaveBeenCalledTimes(2)
|
||||
|
||||
expect(result.size).toBe(2)
|
||||
expect(result.get(mockLnurls[0])).toEqual(mockZapperInfo1)
|
||||
expect(result.get(mockLnurls[1])).toEqual(mockZapperInfo2)
|
||||
})
|
||||
|
||||
it("should fetch zappers directly when dufflepud URL is not provided", async () => {
|
||||
// Arrange
|
||||
ctx.app.dufflepudUrl = undefined
|
||||
|
||||
vi.mocked(fetchJson).mockImplementation(async url => {
|
||||
if (url === mockHexLnurls[0]) return mockZapperInfo1
|
||||
if (url === mockHexLnurls[1]) return mockZapperInfo2
|
||||
throw new Error("Invalid URL")
|
||||
})
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers(mockLnurls)
|
||||
|
||||
// Assert
|
||||
expect(fetchJson).toHaveBeenCalledWith(mockHexLnurls[0])
|
||||
expect(fetchJson).toHaveBeenCalledWith(mockHexLnurls[1])
|
||||
expect(postJson).not.toHaveBeenCalled()
|
||||
|
||||
expect(result.size).toBe(2)
|
||||
expect(result.get(mockLnurls[0])).toEqual(mockZapperInfo1)
|
||||
expect(result.get(mockLnurls[1])).toEqual(mockZapperInfo2)
|
||||
})
|
||||
|
||||
it("should handle invalid lnurls when using dufflepud", async () => {
|
||||
// Arrange
|
||||
ctx.app.dufflepudUrl = "https://dufflepud.com"
|
||||
|
||||
// Make only the first lnurl valid
|
||||
vi.mocked(bech32ToHex).mockImplementation(lnurl => {
|
||||
if (lnurl === mockLnurls[0]) return mockHexLnurls[0]
|
||||
throw new Error("Invalid lnurl")
|
||||
})
|
||||
|
||||
vi.mocked(postJson).mockResolvedValue({
|
||||
data: [{lnurl: mockHexLnurls[0], info: mockZapperInfo1}],
|
||||
})
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers(mockLnurls)
|
||||
|
||||
// Assert
|
||||
expect(postJson).toHaveBeenCalledWith(`${ctx.app.dufflepudUrl}/zapper/info`, {
|
||||
lnurls: [mockHexLnurls[0]],
|
||||
})
|
||||
|
||||
expect(result.size).toBe(1)
|
||||
expect(result.get(mockLnurls[0])).toEqual(mockZapperInfo1)
|
||||
expect(result.get(mockLnurls[1])).toBeUndefined()
|
||||
})
|
||||
|
||||
it("should handle invalid lnurls when fetching directly", async () => {
|
||||
// Arrange
|
||||
ctx.app.dufflepudUrl = undefined
|
||||
|
||||
// Make only the first lnurl valid
|
||||
vi.mocked(bech32ToHex).mockImplementation(lnurl => {
|
||||
if (lnurl === mockLnurls[0]) return mockHexLnurls[0]
|
||||
throw new Error("Invalid lnurl")
|
||||
})
|
||||
|
||||
vi.mocked(fetchJson).mockImplementation(async url => {
|
||||
if (url === mockHexLnurls[0]) return mockZapperInfo1
|
||||
throw new Error("Invalid URL")
|
||||
})
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers(mockLnurls)
|
||||
|
||||
// Assert
|
||||
expect(fetchJson).toHaveBeenCalledWith(mockHexLnurls[0])
|
||||
expect(fetchJson).toHaveBeenCalledTimes(1)
|
||||
|
||||
expect(result.size).toBe(1)
|
||||
expect(result.get(mockLnurls[0])).toEqual(mockZapperInfo1)
|
||||
expect(result.get(mockLnurls[1])).toBeUndefined()
|
||||
})
|
||||
|
||||
it("should handle empty lnurl list", async () => {
|
||||
// Arrange
|
||||
ctx.app.dufflepudUrl = "https://dufflepud.com"
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers([])
|
||||
|
||||
// Assert
|
||||
expect(postJson).not.toHaveBeenCalled()
|
||||
expect(fetchJson).not.toHaveBeenCalled()
|
||||
expect(result.size).toBe(0)
|
||||
})
|
||||
|
||||
it("should handle malformed zapper responses", async () => {
|
||||
// Arrange
|
||||
ctx.app.dufflepudUrl = "https://dufflepud.com"
|
||||
|
||||
vi.mocked(postJson).mockResolvedValue({
|
||||
// Missing data field
|
||||
wrong_field: [],
|
||||
})
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers(mockLnurls)
|
||||
|
||||
// Assert
|
||||
expect(postJson).toHaveBeenCalled()
|
||||
expect(result.size).toBe(0)
|
||||
})
|
||||
|
||||
it("should handle hexToBech32 errors when processing dufflepud response", async () => {
|
||||
// Arrange
|
||||
ctx.app.dufflepudUrl = "https://dufflepud.com"
|
||||
|
||||
vi.mocked(hexToBech32).mockImplementation(() => {
|
||||
throw new Error("Invalid hex")
|
||||
})
|
||||
|
||||
vi.mocked(postJson).mockResolvedValue({
|
||||
data: [
|
||||
{lnurl: mockHexLnurls[0], info: mockZapperInfo1},
|
||||
{lnurl: mockHexLnurls[1], info: mockZapperInfo2},
|
||||
],
|
||||
})
|
||||
|
||||
// Act
|
||||
const result = await fetchZappers(mockLnurls)
|
||||
|
||||
// Assert
|
||||
expect(postJson).toHaveBeenCalled()
|
||||
expect(hexToBech32).toHaveBeenCalled()
|
||||
expect(result.size).toBe(0)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user