161 lines
4.4 KiB
TypeScript
Executable file
161 lines
4.4 KiB
TypeScript
Executable file
import { io } from 'socket.io-client'
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
|
|
import { WebSocketClient } from './client'
|
|
|
|
import type { Socket } from 'socket.io-client'
|
|
|
|
vi.mock('socket.io-client')
|
|
|
|
interface MockSocket extends Partial<Socket> {
|
|
connected: boolean
|
|
on: ReturnType<typeof vi.fn>
|
|
off: ReturnType<typeof vi.fn>
|
|
emit: ReturnType<typeof vi.fn>
|
|
disconnect: ReturnType<typeof vi.fn>
|
|
removeAllListeners: ReturnType<typeof vi.fn>
|
|
connect: ReturnType<typeof vi.fn>
|
|
}
|
|
|
|
describe('WebSocketClient', () => {
|
|
let client: WebSocketClient
|
|
let mockSocket: MockSocket
|
|
|
|
beforeEach(() => {
|
|
mockSocket = {
|
|
connected: false,
|
|
on: vi.fn(),
|
|
off: vi.fn(),
|
|
emit: vi.fn(),
|
|
disconnect: vi.fn(),
|
|
removeAllListeners: vi.fn(),
|
|
connect: vi.fn(),
|
|
}
|
|
|
|
vi.mocked(io).mockReturnValue(mockSocket as unknown as Socket)
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('constructor', () => {
|
|
it('should create client with default config', () => {
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001' })
|
|
expect(client).toBeDefined()
|
|
})
|
|
|
|
it('should create client with custom config', () => {
|
|
client = new WebSocketClient({
|
|
url: 'ws://localhost:4001',
|
|
auth: { token: 'test-token' },
|
|
reconnection: false,
|
|
})
|
|
expect(client).toBeDefined()
|
|
})
|
|
})
|
|
|
|
describe('connect', () => {
|
|
it('should create socket connection', () => {
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001', autoConnect: false })
|
|
client.connect()
|
|
|
|
expect(io).toHaveBeenCalledWith('ws://localhost:4001', expect.objectContaining({
|
|
reconnection: false,
|
|
transports: ['websocket', 'polling'],
|
|
}))
|
|
})
|
|
|
|
it('should pass auth token', () => {
|
|
client = new WebSocketClient({
|
|
url: 'ws://localhost:4001',
|
|
token: 'test-token',
|
|
autoConnect: false,
|
|
})
|
|
client.connect()
|
|
|
|
expect(io).toHaveBeenCalledWith('ws://localhost:4001', expect.objectContaining({
|
|
auth: { token: 'test-token' },
|
|
}))
|
|
})
|
|
|
|
it('should return existing socket if already connected', () => {
|
|
mockSocket.connected = true
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001' })
|
|
const socket1 = client.connect()
|
|
const socket2 = client.connect()
|
|
|
|
expect(socket1).toBe(socket2)
|
|
expect(io).toHaveBeenCalledTimes(1)
|
|
})
|
|
})
|
|
|
|
describe('disconnect', () => {
|
|
it('should disconnect socket', () => {
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001' })
|
|
client.connect()
|
|
client.disconnect()
|
|
|
|
expect(mockSocket.disconnect).toHaveBeenCalled()
|
|
expect(client.getSocket()).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('emit', () => {
|
|
it('should emit event through socket', () => {
|
|
mockSocket.connected = true
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001' })
|
|
client.connect()
|
|
client.emit('test.event', { data: 'test' })
|
|
|
|
expect(mockSocket.emit).toHaveBeenCalledWith('test.event', { data: 'test' })
|
|
})
|
|
|
|
it('should warn if not connected', () => {
|
|
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001', autoConnect: false })
|
|
client.emit('test.event', { data: 'test' })
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
expect.stringContaining('Cannot emit')
|
|
)
|
|
consoleSpy.mockRestore()
|
|
})
|
|
})
|
|
|
|
describe('on', () => {
|
|
it('should register event listener', () => {
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001' })
|
|
client.connect()
|
|
const callback = vi.fn()
|
|
|
|
client.on('test.event', callback)
|
|
|
|
expect(mockSocket.on).toHaveBeenCalledWith('test.event', callback)
|
|
})
|
|
|
|
it('should return unsubscribe function', () => {
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001' })
|
|
client.connect()
|
|
const callback = vi.fn()
|
|
|
|
const unsubscribe = client.on('test.event', callback)
|
|
unsubscribe()
|
|
|
|
expect(mockSocket.off).toHaveBeenCalledWith('test.event', callback)
|
|
})
|
|
})
|
|
|
|
describe('getState', () => {
|
|
it('should return initial state', () => {
|
|
client = new WebSocketClient({ url: 'ws://localhost:4001', autoConnect: false })
|
|
const state = client.getState()
|
|
|
|
expect(state).toEqual({
|
|
connected: false,
|
|
connecting: false,
|
|
error: null,
|
|
})
|
|
})
|
|
})
|
|
})
|