Skip to content
This repository has been archived by the owner on Jun 15, 2024. It is now read-only.

Commit

Permalink
test(wallets/manager): add unit tests for WalletManager
Browse files Browse the repository at this point in the history
  • Loading branch information
drichar committed Dec 5, 2023
1 parent acb81ea commit c2ceb7b
Showing 1 changed file with 267 additions and 0 deletions.
267 changes: 267 additions & 0 deletions __tests__/wallets/manager.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
import { beforeEach, describe, expect, it, jest, spyOn } from 'bun:test'
import { NetworkId } from 'src/network/constants'
import { WalletManager } from 'src/wallets/manager'
import { WalletId } from 'src/wallets/supported/constants'
import { DeflyWallet } from 'src/wallets/supported/defly'
import { PeraWallet } from 'src/wallets/supported/pera'

const deflyResumeSession = spyOn(DeflyWallet.prototype, 'resumeSession').mockImplementation(() =>
Promise.resolve()
)
const peraResumeSession = spyOn(PeraWallet.prototype, 'resumeSession').mockImplementation(() =>
Promise.resolve()
)

// Suppress console output
spyOn(console, 'info').mockImplementation(() => {})
spyOn(console, 'warn').mockImplementation(() => {})
spyOn(console, 'groupCollapsed').mockImplementation(() => {})

// Mock localStorage
const localStorageMock = (() => {
let store: Record<string, any> = {}
return {
getItem: (key: string) => store[key] || null,
setItem: (key: string, value: any) => (store[key] = value.toString()),
clear: () => (store = {})
}
})()
Object.defineProperty(global, 'localStorage', {
value: localStorageMock
})

describe('WalletManager', () => {
beforeEach(() => {
localStorageMock.clear()
})

describe('constructor', () => {
it('initializes with default network and wallets', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
expect(manager.wallets.length).toBe(2)
expect(manager.activeNetwork).toBe(NetworkId.TESTNET)
expect(manager.algodClient).toBeDefined()
})

it('initializes with custom network and wallets', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA],
network: NetworkId.MAINNET
})
expect(manager.wallets.length).toBe(2)
expect(manager.activeNetwork).toBe(NetworkId.MAINNET)
expect(manager.algodClient).toBeDefined()
})

it('initializes with custom algod config', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA],
network: NetworkId.LOCALNET,
algod: {
baseServer: 'http://localhost',
port: '1234',
token: '1234',
headers: {
'X-API-Key': '1234'
}
}
})

expect(manager.wallets.length).toBe(2)
expect(manager.activeNetwork).toBe(NetworkId.LOCALNET)
expect(manager.algodClient).toBeDefined()
})
})

describe('initializeWallets', () => {
it('initializes wallets from string array', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
expect(manager.wallets.length).toBe(2)
})

it('initializes wallets from WalletIdConfig array', () => {
const manager = new WalletManager({
wallets: [
{
id: WalletId.DEFLY,
options: {
shouldShowSignTxnToast: false
}
},
{
id: WalletId.WALLETCONNECT,
options: {
projectId: '1234'
}
}
]
})
expect(manager.wallets.length).toBe(2)
})

it('initializes wallets from mixed array', () => {
const manager = new WalletManager({
wallets: [
WalletId.DEFLY,
{
id: WalletId.WALLETCONNECT,
options: {
projectId: '1234'
}
}
]
})
expect(manager.wallets.length).toBe(2)
})

it('initializes wallets with custom metadata', () => {
const manager = new WalletManager({
wallets: [
{
id: WalletId.DEFLY,
metadata: {
name: 'Custom Wallet',
icon: 'icon'
}
}
]
})
expect(manager.wallets.length).toBe(1)
expect(manager.wallets[0]?.metadata.name).toBe('Custom Wallet')
expect(manager.wallets[0]?.metadata.icon).toBe('icon')
})

// @todo: Test for handling of invalid wallet configurations
})

describe('setActiveNetwork', () => {
it('sets active network correctly', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
manager.setActiveNetwork(NetworkId.MAINNET)
expect(manager.activeNetwork).toBe(NetworkId.MAINNET)
})

// @todo: Test for handling of invalid network
})

describe('subscribe', () => {
it('adds and removes a subscriber', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
const callback = jest.fn()
const unsubscribe = manager.subscribe(callback)

// Trigger a state change
manager.setActiveNetwork(NetworkId.MAINNET)

expect(callback).toHaveBeenCalled()

unsubscribe()
// Trigger another state change
manager.setActiveNetwork(NetworkId.BETANET)

expect(callback).toHaveBeenCalledTimes(1) // Should not be called again
})
})

describe('activeWallet', () => {
const serializedState = {
wallets: {
_type: 'Map',
data: [
[
'pera',
{
accounts: [
{
name: 'Pera Wallet 1',
address: '7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q'
},
{
name: 'Pera Wallet 2',
address: 'N2C374IRX7HEX2YEQWJBTRSVRHRUV4ZSF76S54WV4COTHRUNYRCI47R3WU'
}
],
activeAccount: {
name: 'Pera Wallet 1',
address: '7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q'
}
}
]
]
},
activeWallet: 'pera',
activeNetwork: 'testnet'
}

beforeEach(() => {
localStorageMock.setItem('@txnlab/use-wallet', JSON.stringify(serializedState))
})

it('returns the active wallet', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
expect(manager.activeWallet?.id).toBe(WalletId.PERA)
})

it('returns null if no active wallet', () => {
localStorageMock.clear()

const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
expect(manager.activeWallet).toBeNull()
})

it('returns active wallet accounts', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
expect(manager.activeWalletAccounts?.length).toBe(2)
expect(manager.activeWalletAddresses).toEqual([
'7ZUECA7HFLZTXENRV24SHLU4AVPUTMTTDUFUBNBD64C73F3UHRTHAIOF6Q',
'N2C374IRX7HEX2YEQWJBTRSVRHRUV4ZSF76S54WV4COTHRUNYRCI47R3WU'
])
})

it('removes wallets in state that are not in config', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY]
})
expect(manager.wallets.length).toBe(1)
expect(manager.wallets[0]?.id).toBe(WalletId.DEFLY)
expect(manager.activeWallet).toBeNull()
})
})

describe('Transaction Signing', () => {
it('throws error if no active wallet', () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
expect(() => manager.signTransactions).toThrow()
})

// @todo: Tests for successful signing
})

describe('resumeSessions', () => {
it('resumes sessions for all wallets', async () => {
const manager = new WalletManager({
wallets: [WalletId.DEFLY, WalletId.PERA]
})
await manager.resumeSessions()

expect(deflyResumeSession).toHaveBeenCalled()
expect(peraResumeSession).toHaveBeenCalled()
})
})
})

0 comments on commit c2ceb7b

Please sign in to comment.