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

Commit

Permalink
test(vue): update and add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
drichar committed Jan 4, 2024
1 parent af18c0e commit b3dcd0f
Show file tree
Hide file tree
Showing 3 changed files with 323 additions and 36 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@vitejs/plugin-react": "^4.2.1",
"@vitejs/plugin-vue": "^5.0.2",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/test-utils": "^2.4.3",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
Expand Down
267 changes: 231 additions & 36 deletions packages/use-wallet-vue/src/__tests__/useWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,43 @@ import {
WalletId,
defaultState,
type State,
type WalletAccount
type WalletAccount,
PeraWallet
} from '@txnlab/use-wallet-js'
import { inject } from 'vue'
import { ref } from 'vue-demi'
import { mount } from '@vue/test-utils'
import { inject, nextTick } from 'vue'
import { useWallet, type Wallet } from '../useWallet'

vi.mock('@tanstack/vue-store', async (importOriginal) => {
const mod = await importOriginal<typeof import('@tanstack/vue-store')>()
// Mock localStorage
const localStorageMock = (() => {
let store: Record<string, any> = {}
return {
...mod,
useStore: vi.fn().mockImplementation((store, selector) => {
const state = defaultState
return ref(selector(state))
})
getItem: (key: string) => store[key] || null,
setItem: (key: string, value: any) => (store[key] = value.toString()),
clear: () => (store = {})
}
})()
Object.defineProperty(global, 'localStorage', {
value: localStorageMock
})

vi.mock('vue', async (importOriginal) => {
const mod = await importOriginal<typeof import('vue')>()
const mocks = vi.hoisted(() => {
return {
...mod,
inject: vi.fn().mockImplementation(() => new WalletManager())
connect: vi.fn(() => Promise.resolve([] as WalletAccount[])),
disconnect: vi.fn(() => Promise.resolve()),
setActive: vi.fn(),
setActiveAccount: vi.fn(),
resumeSession: vi.fn(() => Promise.resolve()),
signTransactions: vi.fn(() => Promise.resolve([] as Uint8Array[])),
transactionSigner: vi.fn(() => Promise.resolve([] as Uint8Array[]))
}
})

const {
mockConnect,
mockDisconnect,
mockResumeSession,
mockSignTransactions,
mockTransactionSigner
} = vi.hoisted(() => {
vi.mock('vue', async (importOriginal) => {
const mod = await importOriginal<typeof import('vue')>()
return {
mockConnect: vi.fn(() => Promise.resolve([] as WalletAccount[])),
mockDisconnect: vi.fn(() => Promise.resolve()),
mockResumeSession: vi.fn(() => Promise.resolve()),
mockSignTransactions: vi.fn(() => Promise.resolve([] as Uint8Array[])),
mockTransactionSigner: vi.fn(() => Promise.resolve([] as Uint8Array[]))
...mod,
inject: vi.fn().mockImplementation(() => new WalletManager())
}
})

Expand All @@ -53,11 +52,22 @@ vi.mock('@txnlab/use-wallet-js', async (importOriginal) => {
return {
...mod,
DeflyWallet: class extends mod.BaseWallet {
connect = mockConnect
disconnect = mockDisconnect
resumeSession = mockResumeSession
signTransactions = mockSignTransactions
transactionSigner = mockTransactionSigner
connect = mocks.connect
disconnect = mocks.disconnect
setActive = mocks.setActive
setActiveAccount = mocks.setActiveAccount
resumeSession = mocks.resumeSession
signTransactions = mocks.signTransactions
transactionSigner = mocks.transactionSigner
},
PeraWallet: class extends mod.BaseWallet {
connect = mocks.connect
disconnect = mocks.disconnect
setActive = mocks.setActive
setActiveAccount = mocks.setActiveAccount
resumeSession = mocks.resumeSession
signTransactions = mocks.signTransactions
transactionSigner = mocks.transactionSigner
}
}
})
Expand All @@ -78,16 +88,37 @@ const mockDeflyWallet = new DeflyWallet({
subscribe: mockSubscribe
})

const mockPeraWallet = new PeraWallet({
id: WalletId.PERA,
metadata: { name: 'Pera', icon: 'icon' },
store: mockStore,
subscribe: mockSubscribe
})

describe('useWallet', () => {
let mockWalletManager: WalletManager
let mockWallets: Wallet[]

beforeEach(() => {
mockStore.setState(() => defaultState)

mockWalletManager = new WalletManager()
mockWallets = [
{
id: WalletId.DEFLY,
metadata: { name: 'Defly', icon: 'icon' },
id: mockDeflyWallet.id,
metadata: mockDeflyWallet.metadata,
accounts: [],
activeAccount: null,
isConnected: false,
isActive: false,
connect: expect.any(Function),
disconnect: expect.any(Function),
setActive: expect.any(Function),
setActiveAccount: expect.any(Function)
},
{
id: mockPeraWallet.id,
metadata: mockPeraWallet.metadata,
accounts: [],
activeAccount: null,
isConnected: false,
Expand All @@ -98,7 +129,10 @@ describe('useWallet', () => {
setActiveAccount: expect.any(Function)
}
]
mockWalletManager._clients = new Map<WalletId, BaseWallet>([[WalletId.DEFLY, mockDeflyWallet]])
mockWalletManager._clients = new Map<WalletId, BaseWallet>([
[WalletId.DEFLY, mockDeflyWallet],
[WalletId.PERA, mockPeraWallet]
])
mockWalletManager.store = mockStore
})

Expand All @@ -125,7 +159,168 @@ describe('useWallet', () => {
await wallets.value[0].connect()
await wallets.value[0].disconnect()

expect(mockConnect).toHaveBeenCalled()
expect(mockDisconnect).toHaveBeenCalled()
expect(mocks.connect).toHaveBeenCalled()
expect(mocks.disconnect).toHaveBeenCalled()
})

it('calls setActive and setActiveAccount correctly', () => {
vi.mocked(inject).mockImplementation(() => mockWalletManager)
const { wallets } = useWallet()

// Simulate setActive
wallets.value[0].setActive()
wallets.value[0].setActiveAccount('address')

expect(mocks.setActive).toHaveBeenCalled()
expect(mocks.setActiveAccount).toHaveBeenCalledWith('address')
})

it('calls signTransactions and transactionSigner correctly', async () => {
vi.mocked(inject).mockImplementation(() => mockWalletManager)
const { signTransactions, transactionSigner } = useWallet()

mockStore.setState((state) => ({
...state,
wallets: {
[WalletId.DEFLY]: {
accounts: [
{
name: 'Defly Account 1',
address: 'address1'
}
],
activeAccount: {
name: 'Defly Account 1',
address: 'address1'
}
}
},
activeWallet: WalletId.DEFLY
}))

// Simulate signTransactions and transactionSigner
await signTransactions([], [], true)
await transactionSigner([], [])

expect(mocks.signTransactions).toHaveBeenCalledWith([], [], true)
expect(mocks.transactionSigner).toHaveBeenCalledWith([], [])
})

it('updates wallets when store state changes', () => {
vi.mocked(inject).mockImplementation(() => mockWalletManager)
const { wallets } = useWallet()

mockStore.setState((state) => ({
...state,
wallets: {
[WalletId.DEFLY]: {
accounts: [
{
name: 'Defly Account 1',
address: 'address1'
},
{
name: 'Defly Account 2',
address: 'address2'
}
],
activeAccount: {
name: 'Defly Account 1',
address: 'address1'
}
}
},
activeWallet: WalletId.DEFLY
}))

expect(wallets.value).toEqual([
{
...mockWallets[0],
accounts: [
{
name: 'Defly Account 1',
address: 'address1'
},
{
name: 'Defly Account 2',
address: 'address2'
}
],
activeAccount: {
name: 'Defly Account 1',
address: 'address1'
},
isConnected: true,
isActive: true
},
mockWallets[1]
])
})

it('integrates correctly with Vue component', async () => {
vi.mocked(inject).mockImplementation(() => mockWalletManager)
const { wallets, activeWallet, activeAddress, activeNetwork } = useWallet()

const TestComponent = {
template: `
<div>
<ul>
<li v-for="wallet in wallets" :key="wallet.id" data-testid="wallet">
{{ wallet.metadata.name }}
</li>
</ul>
<div data-testid="activeNetwork">{{ activeNetwork }}</div>
<div data-testid="activeWallet">{{ activeWallet?.id }}</div>
<div data-testid="activeAddress">{{ activeAddress }}</div>
</div>
`,
setup() {
return {
wallets,
activeWallet,
activeAddress,
activeNetwork
}
}
}

const wrapper = mount(TestComponent)

const listItems = wrapper.findAll('[data-testid="wallet"]')
expect(listItems).toHaveLength(2)

mockWallets.forEach((wallet, index) => {
expect(listItems[index].text()).toBe(wallet.metadata.name)
})

expect(wrapper.get('[data-testid="activeNetwork"]').text()).toBe(NetworkId.TESTNET)
expect(wrapper.get('[data-testid="activeWallet"]').text()).toBe('')
expect(wrapper.get('[data-testid="activeAddress"]').text()).toBe('')

// Mock a state change in the store
mockStore.setState((state) => ({
...state,
wallets: {
[WalletId.DEFLY]: {
accounts: [
{
name: 'Defly Account 1',
address: 'address1'
}
],
activeAccount: {
name: 'Defly Account 1',
address: 'address1'
}
}
},
activeWallet: WalletId.DEFLY
}))

await nextTick()

expect(wrapper.get('[data-testid="activeNetwork"]').text()).toBe(NetworkId.TESTNET)
expect(wrapper.get('[data-testid="activeWallet"]').text()).toBe(WalletId.DEFLY)
expect(wrapper.get('[data-testid="activeAddress"]').text()).toBe('address1')
})
})
Loading

0 comments on commit b3dcd0f

Please sign in to comment.