-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathpeer-connection-utils.spec.ts
More file actions
116 lines (103 loc) · 3.83 KB
/
Copy pathpeer-connection-utils.spec.ts
File metadata and controls
116 lines (103 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* eslint-disable */
import { mocked } from './mocks/mock';
import { PeerConnection } from './peer-connection';
import { getLocalDescriptionWithIceCandidates } from './peer-connection-utils';
jest.mock('./peer-connection');
const dummyLocalDesc: RTCSessionDescription = {
type: 'offer',
sdp: 'sdp with candidates',
toJSON: () => ({ type: 'offer', sdp: 'sdp with candidates' }),
};
describe('getLocalDescriptionWithIceCandidates', () => {
const mockPc = mocked(new PeerConnection(), true);
test('return the correct offer after ice gathering has finished', (done) => {
mockPc.getLocalDescription.mockReturnValueOnce(dummyLocalDesc);
const promise = new PromiseHelper(
getLocalDescriptionWithIceCandidates(mockPc as unknown as PeerConnection)
);
expect(mockPc.on.mock.calls).toHaveLength(1);
expect(mockPc.on.mock.calls[0][0]).toBe(PeerConnection.Events.IceGatheringStateChange);
// Grab the listener that was installed
const iceGatheringStateListener = mockPc.on.mock.calls[0][1];
iceGatheringStateListener({
target: {
iceGatheringState: 'gathering',
},
});
// The reason for these nested calls to Promise.resolve is because, unlike many tests around
// Promises, here we're trying to validate that a promise _wasn't_ resolved when it shouldn't
// have been. In order to do that, we make use of PromiseHelper, and also the use of
// Promise.resolve so that the test validation tasks are queued properly with the resolution of
// the promise in the code we're testing.
Promise.resolve().then(() => {
// Verify the promise hasn't been completed yet
expect(promise.isFinished()).toBe(false);
// Now fire another event with the complete state
iceGatheringStateListener({
target: {
iceGatheringState: 'complete',
},
});
// Make sure the helper has had a chance to resolve its promise before we check again
Promise.resolve().then(() => {
expect(mockPc.getLocalDescription.mock.calls).toHaveLength(1);
expect(promise.isFinished()).toBe(true);
expect(promise.resolvedValue).toBe(dummyLocalDesc);
done();
});
});
});
test('rejects if the local description is null', async () => {
mockPc.getLocalDescription.mockReturnValueOnce(null);
const promise = getLocalDescriptionWithIceCandidates(mockPc as unknown as PeerConnection);
const iceGatheringStateListener = mockPc.on.mock.calls[0][1];
iceGatheringStateListener({
target: {
iceGatheringState: 'complete',
},
});
await expect(promise).rejects.toStrictEqual(expect.any(Error));
});
test('resolves immediately if the ICE candidates have already been gathered', () => {
mockPc.getLocalDescription.mockReturnValueOnce(dummyLocalDesc);
Object.defineProperty(mockPc, 'iceGatheringState', {
get: () => 'complete',
});
return getLocalDescriptionWithIceCandidates(mockPc as unknown as PeerConnection);
});
});
/**
* PromiseHelper is a wrapper which enables checking the state of the contained promise.
*/
class PromiseHelper<T> {
resolvedValue?: T;
error?: any;
constructor(promise: Promise<T>) {
promise
.then((value: T) => {
this.resolvedValue = value;
})
.catch((e) => {
this.error = e;
});
}
/**
* Returns true if the Promise has completed (either successfully or unsuccessfully), false
* otherwise.
*/
isFinished(): boolean {
return this.resolvedValue !== undefined || this.error !== undefined;
}
/**
* Returns true if the Promise has completed successfully, false otherwise
*/
isResolved(): boolean {
return this.resolvedValue !== undefined;
}
/**
* Returns true if the Promise has completed unsuccessfully, false otherwise
*/
isError(): boolean {
return this.error !== undefined;
}
}