test: add frontend composable tests and remaining test files
useNostr (9), useFightCache (5), useOnlineStatus (4) composable tests. Added fake-indexeddb dev dependency for IDB tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
806163c6c5
commit
1c296c6f1c
@@ -0,0 +1,131 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||
|
||||
// Mock nostr-tools before importing useNostr
|
||||
vi.mock('nostr-tools', () => ({
|
||||
generateSecretKey: () => new Uint8Array(32).fill(1),
|
||||
getPublicKey: () => 'a'.repeat(64),
|
||||
}))
|
||||
vi.mock('nostr-tools/utils', () => ({
|
||||
bytesToHex: (b: Uint8Array) => Array.from(b).map(x => x.toString(16).padStart(2, '0')).join(''),
|
||||
hexToBytes: (h: string) => new Uint8Array(h.match(/.{2}/g)!.map(x => parseInt(x, 16))),
|
||||
}))
|
||||
vi.mock('nostr-tools/nip19', () => ({
|
||||
nsecEncode: (b: Uint8Array) => 'nsec1mock',
|
||||
}))
|
||||
|
||||
// Mock the auth module
|
||||
const mockAuthFetch = vi.fn().mockResolvedValue({ json: () => Promise.resolve({ exists: false }) })
|
||||
const mockSetToken = vi.fn()
|
||||
const mockGetToken = vi.fn().mockReturnValue(null)
|
||||
const mockIsTokenExpired = vi.fn().mockReturnValue(true)
|
||||
|
||||
vi.mock('../../lib/nostr-auth', () => ({
|
||||
buildNip98Token: vi.fn().mockResolvedValue('mock-nip98-token'),
|
||||
setToken: (...args: unknown[]) => mockSetToken(...args),
|
||||
getToken: () => mockGetToken(),
|
||||
isTokenExpired: () => mockIsTokenExpired(),
|
||||
authFetch: (...args: unknown[]) => mockAuthFetch(...args),
|
||||
}))
|
||||
|
||||
describe('useNostr', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
it('isLoggedIn is false when no pubkey or bot stored', async () => {
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { isLoggedIn, pubkey, bot } = useNostr()
|
||||
expect(isLoggedIn.value).toBe(false)
|
||||
expect(pubkey.value).toBeNull()
|
||||
expect(bot.value).toBeNull()
|
||||
})
|
||||
|
||||
it('logout clears all auth state from localStorage', async () => {
|
||||
localStorage.setItem('bf_pubkey', JSON.stringify('testpub'))
|
||||
localStorage.setItem('bf_bot', JSON.stringify({ id: 'b1', name: 'Bot' }))
|
||||
localStorage.setItem('bf_pic', JSON.stringify('https://example.com/pic.jpg'))
|
||||
localStorage.setItem('bf_nsec', 'secretkey')
|
||||
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { logout } = useNostr()
|
||||
|
||||
logout()
|
||||
|
||||
expect(localStorage.getItem('bf_pubkey')).toBeNull()
|
||||
expect(localStorage.getItem('bf_bot')).toBeNull()
|
||||
expect(localStorage.getItem('bf_pic')).toBeNull()
|
||||
expect(localStorage.getItem('bf_nsec')).toBeNull()
|
||||
expect(mockSetToken).toHaveBeenCalledWith(null)
|
||||
})
|
||||
|
||||
it('hasExtension detects window.nostr', async () => {
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { hasExtension } = useNostr()
|
||||
// No NIP-07 extension in jsdom
|
||||
expect(hasExtension.value).toBe(false)
|
||||
})
|
||||
|
||||
it('hasStoredKey is false when no nsec in localStorage', async () => {
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { hasStoredKey } = useNostr()
|
||||
expect(hasStoredKey.value).toBe(false)
|
||||
})
|
||||
|
||||
it('hasStoredKey is true when nsec pre-set in localStorage', async () => {
|
||||
localStorage.setItem('bf_nsec', 'test-nsec')
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { hasStoredKey } = useNostr()
|
||||
expect(hasStoredKey.value).toBe(true)
|
||||
})
|
||||
|
||||
it('getStoredNsec returns null when no key stored', async () => {
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { getStoredNsec } = useNostr()
|
||||
expect(getStoredNsec()).toBeNull()
|
||||
})
|
||||
|
||||
it('persistKey saves session nsec to localStorage', async () => {
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { persistKey } = useNostr()
|
||||
// Without a session key, persist should be a no-op
|
||||
persistKey()
|
||||
expect(localStorage.getItem('bf_nsec')).toBeNull()
|
||||
})
|
||||
|
||||
it('pubkey and bot are readonly refs', async () => {
|
||||
vi.resetModules()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const result = useNostr()
|
||||
// pubkey and bot should be Readonly refs
|
||||
expect(result.pubkey).toBeDefined()
|
||||
expect(result.bot).toBeDefined()
|
||||
expect(result.isLoggedIn).toBeDefined()
|
||||
expect(result.isLoading).toBeDefined()
|
||||
})
|
||||
|
||||
it('waitForSigner resolves false when no extension', async () => {
|
||||
vi.resetModules()
|
||||
vi.useFakeTimers()
|
||||
const { useNostr } = await import('../useNostr')
|
||||
const { waitForSigner } = useNostr()
|
||||
|
||||
const promise = waitForSigner(500)
|
||||
// Advance timers past the timeout
|
||||
vi.advanceTimersByTime(600)
|
||||
const result = await promise
|
||||
expect(result).toBe(false)
|
||||
vi.useRealTimers()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user