595 lines
21 KiB
JavaScript
595 lines
21 KiB
JavaScript
import { jest } from '@jest/globals';
|
|
import fs from 'fs';
|
|
import * as Path from 'path';
|
|
import process from 'process';
|
|
import { setup, teardown } from 'jest-dev-server';
|
|
import { Signaling, WebSocketSignaling } from "../../src/core/signaling.js";
|
|
import { MockSignaling, reset } from "../mocks/mocksignaling.js";
|
|
import { waitFor, sleep, serverExeName } from "../helpers/testutils.js";
|
|
|
|
const portNumber = 8081;
|
|
const runSignalingIntegration = process.env.RUN_SIGNALING_INTEGRATION === '1';
|
|
const signalingModes = runSignalingIntegration
|
|
? [{ mode: "mock" }, { mode: "http" }, { mode: "websocket" }]
|
|
: [{ mode: "mock" }];
|
|
|
|
jest.setTimeout(10000);
|
|
|
|
function buildServerCommand(args = '') {
|
|
const binaryPath = Path.resolve(`../bin~/${serverExeName()}`);
|
|
const buildEntryPath = Path.resolve('../build/index.js');
|
|
const serverCommand = fs.existsSync(binaryPath)
|
|
? `"${binaryPath}"`
|
|
: `"${process.execPath}" "${buildEntryPath}"`;
|
|
|
|
return `${serverCommand} ${args}`.trim();
|
|
}
|
|
|
|
function getPortForMode(mode, isPrivate) {
|
|
if (mode === 'mock') {
|
|
return portNumber;
|
|
}
|
|
|
|
const publicPorts = { http: portNumber + 1, websocket: portNumber + 2 };
|
|
const privatePorts = { http: portNumber + 3, websocket: portNumber + 4 };
|
|
return (isPrivate ? privatePorts : publicPorts)[mode];
|
|
}
|
|
|
|
function createHttpSignaling(port) {
|
|
return new Signaling(1, `http://localhost:${port}`);
|
|
}
|
|
|
|
function createWebSocketSignaling(port) {
|
|
return new WebSocketSignaling(1, `ws://localhost:${port}`);
|
|
}
|
|
|
|
describe('recording signaling message envelope', () => {
|
|
const OriginalWebSocket = window.WebSocket;
|
|
let sentMessages;
|
|
|
|
beforeEach(() => {
|
|
sentMessages = [];
|
|
window.WebSocket = class {
|
|
constructor() {
|
|
this.readyState = 1;
|
|
}
|
|
|
|
send(message) {
|
|
sentMessages.push(message);
|
|
}
|
|
|
|
close() {
|
|
if (this.onclose) {
|
|
this.onclose();
|
|
}
|
|
}
|
|
};
|
|
});
|
|
|
|
afterEach(() => {
|
|
window.WebSocket = OriginalWebSocket;
|
|
});
|
|
|
|
test('sends recording offer through on-message', () => {
|
|
const signaling = new WebSocketSignaling(1, 'ws://localhost:1234');
|
|
|
|
signaling.sendRecordingOffer({
|
|
recordingId: 'recording-1',
|
|
connectionId: 'room-1',
|
|
participantId: 'participant-1',
|
|
sdp: 'offer-sdp'
|
|
});
|
|
|
|
expect(sentMessages).toHaveLength(1);
|
|
const outer = JSON.parse(sentMessages[0]);
|
|
expect(outer.type).toBe('on-message');
|
|
expect(outer.data.connectionId).toBe('room-1');
|
|
expect(outer.data.message).toEqual({
|
|
type: 'recording-offer',
|
|
data: {
|
|
recordingId: 'recording-1',
|
|
connectionId: 'room-1',
|
|
participantId: 'participant-1',
|
|
sdp: 'offer-sdp'
|
|
}
|
|
});
|
|
});
|
|
|
|
test('dispatches wrapped recording messages as recording events', () => {
|
|
const signaling = new WebSocketSignaling(1, 'ws://localhost:1234');
|
|
let recordingAnswer;
|
|
signaling.addEventListener('recording-answer', (event) => {
|
|
recordingAnswer = event.detail;
|
|
});
|
|
|
|
signaling.websocket.onmessage({
|
|
data: JSON.stringify({
|
|
type: 'on-message',
|
|
from: 'room-1',
|
|
data: JSON.stringify({
|
|
type: 'recording-answer',
|
|
data: {
|
|
recordingId: 'recording-1',
|
|
connectionId: 'room-1',
|
|
sdp: 'answer-sdp'
|
|
}
|
|
})
|
|
})
|
|
});
|
|
|
|
expect(recordingAnswer).toEqual({
|
|
type: 'recording-answer',
|
|
recordingId: 'recording-1',
|
|
connectionId: 'room-1',
|
|
sdp: 'answer-sdp'
|
|
});
|
|
});
|
|
});
|
|
|
|
describe.each(signalingModes)('signaling test in public mode', ({ mode }) => {
|
|
let signaling1;
|
|
let signaling2;
|
|
const connectionId1 = "12345";
|
|
const connectionId2 = "67890";
|
|
const testsdp = "test sdp";
|
|
const testcandidate = "test candidate";
|
|
|
|
beforeAll(async () => {
|
|
if (mode == "mock") {
|
|
reset(false);
|
|
signaling1 = new MockSignaling(1);
|
|
signaling2 = new MockSignaling(1);
|
|
} else {
|
|
const serverPort = getPortForMode(mode, false);
|
|
let cmd = buildServerCommand(`-p ${serverPort}`);
|
|
if (mode == "http") {
|
|
cmd += " -t http";
|
|
}
|
|
|
|
await setup({ command: cmd, port: serverPort, usedPortAction: 'error' });
|
|
|
|
if (mode == "http") {
|
|
signaling1 = createHttpSignaling(serverPort);
|
|
signaling2 = createHttpSignaling(serverPort);
|
|
}
|
|
|
|
if (mode == "websocket") {
|
|
signaling1 = createWebSocketSignaling(serverPort);
|
|
signaling2 = createWebSocketSignaling(serverPort);
|
|
}
|
|
}
|
|
|
|
await signaling1.start();
|
|
await signaling2.start();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await signaling1?.stop();
|
|
await signaling2?.stop();
|
|
signaling1 = null;
|
|
signaling2 = null;
|
|
|
|
if (mode == "mock") {
|
|
return;
|
|
}
|
|
|
|
await teardown();
|
|
// work around for linux, waitng kill server process
|
|
await sleep(1000);
|
|
});
|
|
|
|
test(`onConnect using ${mode}`, async () => {
|
|
const signaling1Spy = jest.spyOn(signaling1, 'dispatchEvent');
|
|
let connectRes;
|
|
let disconnectRes;
|
|
signaling1.addEventListener('connect', (e) => connectRes = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId1);
|
|
await waitFor(() => connectRes != null);
|
|
expect(connectRes.connectionId).toBe(connectionId1);
|
|
expect(connectRes.polite).toBe(true);
|
|
|
|
await signaling1.deleteConnection(connectionId1);
|
|
await waitFor(() => disconnectRes != null);
|
|
expect(disconnectRes.connectionId).toBe(connectionId1);
|
|
|
|
const disconnectCalledCount = signaling1Spy.mock.calls.map(x => x[0].type).filter(x => x == "disconnect").length;
|
|
expect(disconnectCalledCount).toBe(1);
|
|
|
|
signaling1Spy.mockRestore();
|
|
});
|
|
|
|
test(`onOffer using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId1);
|
|
await signaling2.createConnection(connectionId2);
|
|
await waitFor(() => connectRes1 != null && connectRes2 != null);
|
|
expect(connectRes1.connectionId).toBe(connectionId1);
|
|
expect(connectRes2.connectionId).toBe(connectionId2);
|
|
|
|
await signaling1.sendOffer(connectionId1, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
expect(offerRes2.connectionId).toBe(connectionId1);
|
|
expect(offerRes2.polite).toBe(false);
|
|
|
|
await signaling1.deleteConnection(connectionId1);
|
|
await waitFor(() => disconnectRes1 != null);
|
|
expect(disconnectRes1.connectionId).toBe(connectionId1);
|
|
await signaling2.deleteConnection(connectionId2);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
expect(disconnectRes2.connectionId).toBe(connectionId2);
|
|
});
|
|
|
|
test(`onAnswer using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
let answerRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
signaling1.addEventListener('answer', (e) => answerRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId1);
|
|
await signaling2.createConnection(connectionId2);
|
|
await waitFor(() => connectRes1 != null && connectRes2 != null);
|
|
|
|
await signaling1.sendOffer(connectionId1, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
expect(offerRes2.connectionId).toBe(connectionId1);
|
|
expect(offerRes2.sdp).toBe(testsdp);
|
|
|
|
signaling2.sendAnswer(connectionId1, testsdp);
|
|
await waitFor(() => answerRes1 != null);
|
|
expect(answerRes1.connectionId).toBe(connectionId1);
|
|
expect(answerRes1.sdp).toBe(testsdp);
|
|
|
|
await signaling1.deleteConnection(connectionId1);
|
|
await waitFor(() => disconnectRes1 != null);
|
|
await signaling2.deleteConnection(connectionId2);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
|
|
test(`onCandidate using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
let answerRes1;
|
|
let candidateRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
signaling1.addEventListener('answer', (e) => answerRes1 = e.detail);
|
|
signaling1.addEventListener('candidate', (e) => candidateRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
let candidateRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
signaling2.addEventListener('candidate', (e) => candidateRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId1);
|
|
await signaling2.createConnection(connectionId2);
|
|
await waitFor(() => connectRes1 != null && connectRes2 != null);
|
|
|
|
await signaling1.sendOffer(connectionId1, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
expect(offerRes2.connectionId).toBe(connectionId1);
|
|
expect(offerRes2.sdp).toBe(testsdp);
|
|
|
|
signaling2.sendAnswer(connectionId1, testsdp);
|
|
await waitFor(() => answerRes1 != null);
|
|
expect(answerRes1.connectionId).toBe(connectionId1);
|
|
expect(answerRes1.sdp).toBe(testsdp);
|
|
|
|
await signaling2.sendCandidate(connectionId1, testcandidate, 1, 1);
|
|
await waitFor(() => candidateRes1 != null);
|
|
expect(candidateRes1.connectionId).toBe(connectionId1);
|
|
expect(candidateRes1.candidate).toBe(testcandidate);
|
|
expect(candidateRes1.sdpMid).toBe(1);
|
|
expect(candidateRes1.sdpMLineIndex).toBe(1);
|
|
|
|
await signaling1.sendCandidate(connectionId1, testcandidate, 1, 1);
|
|
await waitFor(() => candidateRes2 != null);
|
|
expect(candidateRes2.connectionId).toBe(connectionId1);
|
|
expect(candidateRes2.candidate).toBe(testcandidate);
|
|
expect(candidateRes2.sdpMid).toBe(1);
|
|
expect(candidateRes2.sdpMLineIndex).toBe(1);
|
|
|
|
await signaling1.deleteConnection(connectionId1);
|
|
await waitFor(() => disconnectRes1 != null);
|
|
await signaling2.deleteConnection(connectionId2);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
});
|
|
|
|
describe.each(signalingModes)('signaling test in private mode', ({ mode }) => {
|
|
let signaling1;
|
|
let signaling2;
|
|
const connectionId = "12345";
|
|
const testsdp = "test sdp";
|
|
const testcandidate = "test candidate";
|
|
|
|
beforeAll(async () => {
|
|
if (mode == "mock") {
|
|
reset(true);
|
|
signaling1 = new MockSignaling(1);
|
|
signaling2 = new MockSignaling(1);
|
|
return;
|
|
}
|
|
|
|
const serverPort = getPortForMode(mode, true);
|
|
let cmd = buildServerCommand(`-p ${serverPort} -m private`);
|
|
if (mode == "http") {
|
|
cmd += " -t http";
|
|
}
|
|
|
|
await setup({ command: cmd, port: serverPort, usedPortAction: 'error' });
|
|
|
|
if (mode == "http") {
|
|
signaling1 = createHttpSignaling(serverPort);
|
|
signaling2 = createHttpSignaling(serverPort);
|
|
}
|
|
|
|
if (mode == "websocket") {
|
|
signaling1 = createWebSocketSignaling(serverPort);
|
|
signaling2 = createWebSocketSignaling(serverPort);
|
|
}
|
|
|
|
await signaling1.start();
|
|
await signaling2.start();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await signaling1?.stop();
|
|
await signaling2?.stop();
|
|
signaling1 = null;
|
|
signaling2 = null;
|
|
|
|
if (mode == "mock") {
|
|
return;
|
|
}
|
|
|
|
await teardown();
|
|
// work around for linux, waitng kill server process
|
|
await sleep(1000);
|
|
});
|
|
|
|
test(`onConnect using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId);
|
|
await waitFor(() => connectRes1 != null);
|
|
expect(connectRes1.connectionId).toBe(connectionId);
|
|
expect(connectRes1.polite).toBe(false);
|
|
|
|
await signaling2.createConnection(connectionId);
|
|
await waitFor(() => connectRes2 != null);
|
|
expect(connectRes2.connectionId).toBe(connectionId);
|
|
expect(connectRes2.polite).toBe(true);
|
|
|
|
await sleep(signaling1.interval * 2);
|
|
|
|
await signaling1.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes1 != null && disconnectRes2 != null);
|
|
expect(disconnectRes1.connectionId).toBe(connectionId);
|
|
expect(disconnectRes2.connectionId).toBe(connectionId);
|
|
|
|
disconnectRes2 = null;
|
|
await signaling2.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
|
|
test(`onOffer using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId);
|
|
await waitFor(() => connectRes1 != null);
|
|
expect(connectRes1.connectionId).toBe(connectionId);
|
|
|
|
signaling1.sendOffer(connectionId, testsdp);
|
|
await sleep(signaling1.interval * 2);
|
|
// Do not receive offer other signaling if not connected same sendoffer connectionId in private mode
|
|
expect(offerRes2).toBeUndefined();
|
|
|
|
await signaling2.createConnection(connectionId);
|
|
await waitFor(() => connectRes2 != null);
|
|
expect(connectRes2.connectionId).toBe(connectionId);
|
|
|
|
await signaling1.sendOffer(connectionId, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
expect(offerRes2.connectionId).toBe(connectionId);
|
|
expect(offerRes2.polite).toBe(true);
|
|
|
|
await signaling1.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes1 != null && disconnectRes2 != null);
|
|
expect(disconnectRes1.connectionId).toBe(connectionId);
|
|
expect(disconnectRes2.connectionId).toBe(connectionId);
|
|
|
|
disconnectRes2 = null;
|
|
await signaling2.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
|
|
test(`onAnswer using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
let answerRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
signaling1.addEventListener('answer', (e) => answerRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId);
|
|
await signaling2.createConnection(connectionId);
|
|
await waitFor(() => connectRes1 != null && connectRes2 != null);
|
|
|
|
await signaling1.sendOffer(connectionId, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
expect(offerRes2.connectionId).toBe(connectionId);
|
|
expect(offerRes2.sdp).toBe(testsdp);
|
|
|
|
await signaling2.sendAnswer(connectionId, testsdp);
|
|
await waitFor(() => answerRes1 != null);
|
|
expect(answerRes1.connectionId).toBe(connectionId);
|
|
expect(answerRes1.sdp).toBe(testsdp);
|
|
|
|
await signaling1.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes1 != null && disconnectRes2 != null);
|
|
expect(disconnectRes1.connectionId).toBe(connectionId);
|
|
expect(disconnectRes2.connectionId).toBe(connectionId);
|
|
|
|
disconnectRes2 = null;
|
|
await signaling2.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
|
|
test(`onCandidate using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
let answerRes1;
|
|
let candidateRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
signaling1.addEventListener('answer', (e) => answerRes1 = e.detail);
|
|
signaling1.addEventListener('candidate', (e) => candidateRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
let candidateRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
signaling2.addEventListener('candidate', (e) => candidateRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId);
|
|
await signaling2.createConnection(connectionId);
|
|
await waitFor(() => connectRes1 != null && connectRes2 != null);
|
|
|
|
await signaling1.sendOffer(connectionId, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
expect(offerRes2.connectionId).toBe(connectionId);
|
|
expect(offerRes2.sdp).toBe(testsdp);
|
|
|
|
await signaling2.sendAnswer(connectionId, testsdp);
|
|
await waitFor(() => answerRes1 != null);
|
|
expect(answerRes1.connectionId).toBe(connectionId);
|
|
expect(answerRes1.sdp).toBe(testsdp);
|
|
|
|
await signaling2.sendCandidate(connectionId, testcandidate, 1, 1);
|
|
await waitFor(() => candidateRes1 != null);
|
|
expect(candidateRes1.connectionId).toBe(connectionId);
|
|
expect(candidateRes1.candidate).toBe(testcandidate);
|
|
expect(candidateRes1.sdpMLineIndex).toBe(1);
|
|
expect(candidateRes1.sdpMid).toBe(1);
|
|
|
|
await signaling1.sendCandidate(connectionId, testcandidate, 1, 1);
|
|
await waitFor(() => candidateRes2 != null);
|
|
expect(candidateRes2.connectionId).toBe(connectionId);
|
|
expect(candidateRes2.candidate).toBe(testcandidate);
|
|
expect(candidateRes2.sdpMLineIndex).toBe(1);
|
|
expect(candidateRes2.sdpMid).toBe(1);
|
|
|
|
await signaling1.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes1 != null && disconnectRes2 != null);
|
|
expect(disconnectRes1.connectionId).toBe(connectionId);
|
|
expect(disconnectRes2.connectionId).toBe(connectionId);
|
|
|
|
disconnectRes2 = null;
|
|
await signaling2.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
|
|
test(`notReceiveOwnOfferAnswer using ${mode}`, async () => {
|
|
let connectRes1;
|
|
let disconnectRes1;
|
|
let offerRes1;
|
|
let answerRes1;
|
|
signaling1.addEventListener('connect', (e) => connectRes1 = e.detail);
|
|
signaling1.addEventListener('disconnect', (e) => disconnectRes1 = e.detail);
|
|
|
|
let connectRes2;
|
|
let disconnectRes2;
|
|
let offerRes2;
|
|
let answerRes2;
|
|
signaling2.addEventListener('connect', (e) => connectRes2 = e.detail);
|
|
signaling2.addEventListener('disconnect', (e) => disconnectRes2 = e.detail);
|
|
|
|
await signaling1.createConnection(connectionId);
|
|
await signaling2.createConnection(connectionId);
|
|
await waitFor(() => connectRes1 != null && connectRes2 != null);
|
|
|
|
signaling1.addEventListener('offer', (e) => offerRes1 = e.detail);
|
|
signaling2.addEventListener('offer', (e) => offerRes2 = e.detail);
|
|
await signaling1.sendOffer(connectionId, testsdp);
|
|
await waitFor(() => offerRes2 != null);
|
|
await sleep(signaling1.interval * 2);
|
|
expect(offerRes1).toBeUndefined();
|
|
expect(offerRes2).not.toBeUndefined();
|
|
expect(offerRes2.connectionId).toBe(connectionId);
|
|
expect(offerRes2.sdp).toBe(testsdp);
|
|
|
|
signaling1.addEventListener('answer', (e) => answerRes1 = e.detail);
|
|
signaling2.addEventListener('answer', (e) => answerRes2 = e.detail);
|
|
await signaling2.sendAnswer(connectionId, testsdp);
|
|
await waitFor(() => answerRes1 != null);
|
|
await sleep(signaling2.interval * 2);
|
|
expect(answerRes1).not.toBeUndefined();
|
|
expect(answerRes1.connectionId).toBe(connectionId);
|
|
expect(answerRes1.sdp).toBe(testsdp);
|
|
expect(answerRes2).toBeUndefined();
|
|
|
|
await signaling1.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes1 != null && disconnectRes2 != null);
|
|
expect(disconnectRes1.connectionId).toBe(connectionId);
|
|
expect(disconnectRes2.connectionId).toBe(connectionId);
|
|
|
|
disconnectRes2 = null;
|
|
await signaling2.deleteConnection(connectionId);
|
|
await waitFor(() => disconnectRes2 != null);
|
|
});
|
|
});
|