You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.8 KiB

import {
CONNECTION_TRANSPORT_STATE_CLOSED,
CONNECTION_TRANSPORT_STATE_CLOSING,
CONNECTION_TRANSPORT_STATE_IDLE,
CONNECTION_TRANSPORT_STATE_OPEN,
CONNECTION_TRANSPORT_STATE_OPENING,
MOCK_TRANSPORT_DEFAULT_CLOSE_CLEAN,
MOCK_TRANSPORT_DEFAULT_CLOSE_CODE,
TRANSPORT_KIND_MOCK
} from '../consts.ts';
import { createTransportEmitter } from '../transport.ts';
import type {
ConnectionCloseEvent,
ConnectionTransportState,
MockConnectionTransport,
MockTransportOptions
} from '../types.ts';
export function createMockTransport(options: MockTransportOptions = {}): MockConnectionTransport {
const autoOpen = options.autoOpen ?? true;
const openEmitter = createTransportEmitter<() => void>();
const messageEmitter = createTransportEmitter<(message: string | ArrayBuffer) => void>();
const closeEmitter = createTransportEmitter<(event: ConnectionCloseEvent) => void>();
const errorEmitter = createTransportEmitter<(error: unknown) => void>();
const sent: (string | ArrayBuffer)[] = [];
let state: ConnectionTransportState = CONNECTION_TRANSPORT_STATE_IDLE;
const openResolvers = new Set<() => void>();
function resolveOpenWaiters(): void {
for (const resolve of openResolvers) resolve();
openResolvers.clear();
}
function emitOpen(): void {
state = CONNECTION_TRANSPORT_STATE_OPEN;
resolveOpenWaiters();
openEmitter.emit();
}
function emitClose(event: Partial<ConnectionCloseEvent> = {}): void {
state = CONNECTION_TRANSPORT_STATE_CLOSED;
resolveOpenWaiters();
closeEmitter.emit({
code: event.code ?? MOCK_TRANSPORT_DEFAULT_CLOSE_CODE,
reason: event.reason,
clean: event.clean ?? MOCK_TRANSPORT_DEFAULT_CLOSE_CLEAN
});
}
return {
kind: TRANSPORT_KIND_MOCK,
get state() {
return state;
},
get bufferedAmount() {
return sent.length;
},
get canSend() {
return state === CONNECTION_TRANSPORT_STATE_OPEN;
},
open() {
if (state === CONNECTION_TRANSPORT_STATE_OPEN) return Promise.resolve();
state = CONNECTION_TRANSPORT_STATE_OPENING;
if (autoOpen) {
emitOpen();
return Promise.resolve();
}
return new Promise<void>((resolve) => {
openResolvers.add(resolve);
});
},
send(data) {
sent.push(data);
},
close(code, reason) {
if (state === CONNECTION_TRANSPORT_STATE_CLOSED) return;
state = CONNECTION_TRANSPORT_STATE_CLOSING;
emitClose({ code, reason });
},
onOpen: (listener) => openEmitter.on(listener),
onMessage: (listener) => messageEmitter.on(listener),
onClose: (listener) => closeEmitter.on(listener),
onError: (listener) => errorEmitter.on(listener),
emitOpen,
emitMessage(message) {
messageEmitter.emit(message);
},
emitClose,
emitError(error) {
errorEmitter.emit(error);
},
sentMessages() {
return [...sent];
},
clearSent() {
sent.length = 0;
}
};
}

Powered by TurnKey Linux.