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
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;
|
|
}
|
|
};
|
|
}
|