54 lines
3.7 KiB
TypeScript
54 lines
3.7 KiB
TypeScript
import { flushPromises, mount } from '@vue/test-utils'
|
|||
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||
|
|
import LightningChannelsPanel from '../LightningChannelsPanel.vue'
|
||
|
|
import { rpcClient } from '@/api/rpc-client'
|
||
|
|
vi.mock('@/api/rpc-client', () => ({ rpcClient: { call: vi.fn() } }))
|
||
|
|
vi.mock('@/composables/useTxExplorer', () => ({ useTxExplorer: () => ({ openTx: vi.fn() }) }))
|
||
|
|
vi.mock('@/composables/useCachedResource', async () => {
|
||
|
|
const { ref } = await import('vue')
|
||
|
|
return { useCachedResource: () => ({ data: ref(null), loadState: ref('ready'), error: ref(null), refresh: vi.fn().mockResolvedValue(undefined) }) }
|
||
|
|
})
|
||
|
|
const channel = { chan_id: 'test', remote_pubkey: '02' + 'a'.repeat(64), channel_point: 'b'.repeat(64) + ':0', capacity: 100000, local_balance: 50000, remote_balance: 50000, active: true }
|
||
|
|
function open() {
|
||
|
|
const wrapper = mount(LightningChannelsPanel, { global: { stubs: { Teleport: true } } })
|
||
|
|
const vm = (wrapper.vm as any).$.setupState
|
||
|
|
vm.confirmClose(channel)
|
||
|
|
return { wrapper, vm }
|
||
|
|
}
|
||
|
|
beforeEach(() => { vi.clearAllMocks(); vi.mocked(rpcClient.call).mockResolvedValue({ success: true } as never) })
|
||
|
|
describe('channel closing fee choice', () => {
|
||
|
|
it.each([['standard', 6], ['medium', 3], ['fast', 1]])('forwards %s target and never automatically retries the mutation', async (preset, target) => {
|
||
|
|
const { wrapper, vm } = open(); vm.closeForm.feePreset = preset
|
||
|
|
await vm.closeChannel()
|
||
|
|
expect(rpcClient.call).toHaveBeenCalledWith(expect.objectContaining({ method: 'lnd.closechannel', params: { channel_point: channel.channel_point, target_conf: target }, maxRetries: 1 }))
|
||
|
|
expect(vm.closeTarget).toBeNull(); wrapper.unmount()
|
||
|
|
})
|
||
|
|
it('sends the custom rate instead of a confirmation target', async () => {
|
||
|
|
const { wrapper, vm } = open(); vm.closeForm.feePreset = 'custom'; vm.closeForm.customSatPerVbyte = 25; vm.closeForm.customConfTarget = 3
|
||
|
|
await vm.closeChannel()
|
||
|
|
expect(rpcClient.call).toHaveBeenCalledWith(expect.objectContaining({ params: { channel_point: channel.channel_point, sat_per_vbyte: 25 } }))
|
||
|
|
wrapper.unmount()
|
||
|
|
})
|
||
|
|
it.each([0.5, -1, 5001, NaN, Infinity])('rejects invalid custom rate %s before RPC', async rate => {
|
||
|
|
const { wrapper, vm } = open(); vm.closeForm.feePreset = 'custom'; vm.closeForm.customSatPerVbyte = rate
|
||
|
|
await vm.closeChannel(); expect(rpcClient.call).not.toHaveBeenCalled(); expect(vm.closeError).toBeTruthy(); wrapper.unmount()
|
||
|
|
})
|
||
|
|
it('requires a custom value and accepts a custom confirmation target', async () => {
|
||
|
|
const { wrapper, vm } = open(); vm.closeForm.feePreset = 'custom'
|
||
|
|
await vm.closeChannel(); expect(rpcClient.call).not.toHaveBeenCalled()
|
||
|
|
vm.closeForm.customConfTarget = 2; await vm.closeChannel()
|
||
|
|
expect(rpcClient.call).toHaveBeenCalledWith(expect.objectContaining({ params: { channel_point: channel.channel_point, target_conf: 2 } })); wrapper.unmount()
|
||
|
|
})
|
||
|
|
it('keeps the chosen fee and error visible when LND rejects a close', async () => {
|
||
|
|
vi.mocked(rpcClient.call).mockRejectedValue(new Error('Peer is offline'))
|
||
|
|
const { wrapper, vm } = open(); vm.closeForm.feePreset = 'fast'
|
||
|
|
await vm.closeChannel(); expect(vm.closeTarget).not.toBeNull(); expect(vm.closeError).toBe('Peer is offline'); expect(vm.closeForm.feePreset).toBe('fast'); wrapper.unmount()
|
||
|
|
})
|
||
|
|
it('prevents duplicate submits while a close is pending', async () => {
|
||
|
|
let finish!: (value: unknown) => void
|
||
|
|
vi.mocked(rpcClient.call).mockImplementation(() => new Promise(resolve => { finish = resolve }) as never)
|
||
|
|
const { wrapper, vm } = open(); const pending = vm.closeChannel(); await vm.closeChannel()
|
||
|
|
expect(rpcClient.call).toHaveBeenCalledTimes(1); finish({ success: true }); await pending; await flushPromises(); wrapper.unmount()
|
||
|
|
})
|
||
|
|
})
|