src/ws/errors.test.ts
v0.3.0 · 4.4 KB
import { describe, expect, it } from 'vitest';
import { classifyWsServerError, WsLimitError } from './errors.js';
describe('classifyWsServerError', () => {
it('recognizes the user-tracking capacity refusal and keeps the socket', () => {
expect(classifyWsServerError('Cannot track more than 15 total users')).toEqual({ kind: 'userLimit', limit: 15, terminate: false });
});
it('matches case-insensitively and without a number', () => {
expect(classifyWsServerError('CANNOT TRACK MORE THAN many users').kind).toBe('userLimit');
expect(classifyWsServerError('cannot track more than 10 total users').limit).toBe(10);
});
it('recognizes the subscription cap text', () => {
expect(classifyWsServerError('Cannot subscribe to more than 1000 channels.')).toMatchObject({
kind: 'subscriptionLimit',
limit: 1000,
terminate: false,
});
});
it('already subscribed / unsubscribed are not fatal', () => {
expect(classifyWsServerError('Already subscribed: {"type":"l2Book","coin":"BTC"}')).toEqual({
kind: 'alreadySubscribed',
terminate: false,
echo: { type: 'l2Book', coin: 'BTC' },
});
expect(classifyWsServerError('Already unsubscribed: {"type":"trades","coin":"ETH"}').kind).toBe('alreadyUnsubscribed');
});
it('invalid subscription with an echo is attributable and does not terminate', () => {
const info = classifyWsServerError('Invalid subscription {"type":"userFills","user":"0xBAD"}');
expect(info.kind).toBe('invalidSubscription');
expect(info.terminate).toBe(false);
expect(info.echo).toEqual({ type: 'userFills', user: '0xBAD' });
});
it('extracts the subscription from a method envelope echo', () => {
const info = classifyWsServerError('Invalid subscription {"method":"subscribe","subscription":{"type":"bbo","coin":"X"}}');
expect(info.echo).toEqual({ type: 'bbo', coin: 'X' });
});
it('invalid subscription without echo terminates', () => {
expect(classifyWsServerError('Invalid subscription').terminate).toBe(true);
});
it('unknown errors terminate (HL can leave a failed socket open)', () => {
expect(classifyWsServerError('Something went wrong')).toEqual({ kind: 'other', terminate: true });
});
it('survives non-string payloads and broken JSON echoes', () => {
expect(classifyWsServerError({ foo: 1 }).kind).toBe('other');
expect(classifyWsServerError(undefined).kind).toBe('other');
expect(classifyWsServerError('Invalid subscription {not json}').echo).toBeUndefined();
expect(classifyWsServerError('Invalid subscription {"a":1}').echo).toBeUndefined();
});
});
describe('WsLimitError', () => {
it('carries reason, limit and usage', () => {
const e = new WsLimitError('maxUniqueUsers', 'msg', 10, 10);
expect(e).toBeInstanceOf(Error);
expect(e.name).toBe('WsLimitError');
expect([e.reason, e.limit, e.used]).toEqual(['maxUniqueUsers', 10, 10]);
});
});
describe('classifyWsServerError: texts captured on the live socket (2026-09-15)', () => {
it('request-parse refusal with a subscription echo is an attributable invalid subscription', () => {
const info = classifyWsServerError(
'Error parsing JSON into valid websocket request: {"method":"subscribe","subscription":{"type":"candle","coin":"BTC","interval":"7m"}}',
);
expect(info).toEqual({ kind: 'invalidSubscription', terminate: false, echo: { type: 'candle', coin: 'BTC', interval: '7m' } });
});
it('request-parse refusal without an attributable subscription terminates', () => {
expect(classifyWsServerError('Error parsing JSON into valid websocket request: not json')).toMatchObject({
kind: 'invalidSubscription',
terminate: true,
});
expect(classifyWsServerError('Error parsing JSON into valid websocket request: {"method":"subscribe"}').terminate).toBe(true);
});
it('"Invalid subscription {json}" exactly as sent by the server', () => {
expect(classifyWsServerError('Invalid subscription {"type":"activeAssetCtx","coin":"NOPE_COIN"}')).toEqual({
kind: 'invalidSubscription',
terminate: false,
echo: { type: 'activeAssetCtx', coin: 'NOPE_COIN' },
});
});
it('"Already subscribed" for allMids with dex "" echoes the main-dex form', () => {
expect(classifyWsServerError('Already subscribed: {"type":"allMids"}')).toEqual({
kind: 'alreadySubscribed',
terminate: false,
echo: { type: 'allMids' },
});
});
});