@tomgiee/tsdp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +124 -0
- package/dist/src/builder/media-builder.d.ts +221 -0
- package/dist/src/builder/media-builder.d.ts.map +1 -0
- package/dist/src/builder/media-builder.js +385 -0
- package/dist/src/builder/session-builder.d.ts +195 -0
- package/dist/src/builder/session-builder.d.ts.map +1 -0
- package/dist/src/builder/session-builder.js +366 -0
- package/dist/src/index.d.ts +67 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +250 -0
- package/dist/src/parser/attribute-parser.d.ts +100 -0
- package/dist/src/parser/attribute-parser.d.ts.map +1 -0
- package/dist/src/parser/attribute-parser.js +217 -0
- package/dist/src/parser/field-parser.d.ts +124 -0
- package/dist/src/parser/field-parser.d.ts.map +1 -0
- package/dist/src/parser/field-parser.js +335 -0
- package/dist/src/parser/media-parser.d.ts +45 -0
- package/dist/src/parser/media-parser.d.ts.map +1 -0
- package/dist/src/parser/media-parser.js +157 -0
- package/dist/src/parser/primitive-parser.d.ts +138 -0
- package/dist/src/parser/primitive-parser.d.ts.map +1 -0
- package/dist/src/parser/primitive-parser.js +316 -0
- package/dist/src/parser/scanner.d.ts +142 -0
- package/dist/src/parser/scanner.d.ts.map +1 -0
- package/dist/src/parser/scanner.js +284 -0
- package/dist/src/parser/session-parser.d.ts +35 -0
- package/dist/src/parser/session-parser.d.ts.map +1 -0
- package/dist/src/parser/session-parser.js +207 -0
- package/dist/src/parser/time-parser.d.ts +74 -0
- package/dist/src/parser/time-parser.d.ts.map +1 -0
- package/dist/src/parser/time-parser.js +168 -0
- package/dist/src/serializer/attribute-serializer.d.ts +18 -0
- package/dist/src/serializer/attribute-serializer.d.ts.map +1 -0
- package/dist/src/serializer/attribute-serializer.js +34 -0
- package/dist/src/serializer/field-serializer.d.ts +112 -0
- package/dist/src/serializer/field-serializer.d.ts.map +1 -0
- package/dist/src/serializer/field-serializer.js +212 -0
- package/dist/src/serializer/media-serializer.d.ts +31 -0
- package/dist/src/serializer/media-serializer.d.ts.map +1 -0
- package/dist/src/serializer/media-serializer.js +83 -0
- package/dist/src/serializer/session-serializer.d.ts +29 -0
- package/dist/src/serializer/session-serializer.d.ts.map +1 -0
- package/dist/src/serializer/session-serializer.js +99 -0
- package/dist/src/serializer/time-serializer.d.ts +46 -0
- package/dist/src/serializer/time-serializer.d.ts.map +1 -0
- package/dist/src/serializer/time-serializer.js +86 -0
- package/dist/src/types/attributes.d.ts +318 -0
- package/dist/src/types/attributes.d.ts.map +1 -0
- package/dist/src/types/attributes.js +225 -0
- package/dist/src/types/errors.d.ts +129 -0
- package/dist/src/types/errors.d.ts.map +1 -0
- package/dist/src/types/errors.js +186 -0
- package/dist/src/types/fields.d.ts +100 -0
- package/dist/src/types/fields.d.ts.map +1 -0
- package/dist/src/types/fields.js +48 -0
- package/dist/src/types/media.d.ts +148 -0
- package/dist/src/types/media.d.ts.map +1 -0
- package/dist/src/types/media.js +137 -0
- package/dist/src/types/network.d.ts +136 -0
- package/dist/src/types/network.d.ts.map +1 -0
- package/dist/src/types/network.js +130 -0
- package/dist/src/types/primitives.d.ts +193 -0
- package/dist/src/types/primitives.d.ts.map +1 -0
- package/dist/src/types/primitives.js +195 -0
- package/dist/src/types/session.d.ts +122 -0
- package/dist/src/types/session.d.ts.map +1 -0
- package/dist/src/types/session.js +81 -0
- package/dist/src/types/time.d.ts +129 -0
- package/dist/src/types/time.d.ts.map +1 -0
- package/dist/src/types/time.js +84 -0
- package/dist/src/utils/address-parser.d.ts +100 -0
- package/dist/src/utils/address-parser.d.ts.map +1 -0
- package/dist/src/utils/address-parser.js +338 -0
- package/dist/src/utils/format-validators.d.ts +77 -0
- package/dist/src/utils/format-validators.d.ts.map +1 -0
- package/dist/src/utils/format-validators.js +504 -0
- package/dist/src/utils/line-reader.d.ts +84 -0
- package/dist/src/utils/line-reader.d.ts.map +1 -0
- package/dist/src/utils/line-reader.js +169 -0
- package/dist/src/utils/time-converter.d.ts +99 -0
- package/dist/src/utils/time-converter.d.ts.map +1 -0
- package/dist/src/utils/time-converter.js +195 -0
- package/dist/src/validator/media-validator.d.ts +27 -0
- package/dist/src/validator/media-validator.d.ts.map +1 -0
- package/dist/src/validator/media-validator.js +241 -0
- package/dist/src/validator/semantic-validator.d.ts +47 -0
- package/dist/src/validator/semantic-validator.d.ts.map +1 -0
- package/dist/src/validator/semantic-validator.js +207 -0
- package/dist/src/validator/session-validator.d.ts +36 -0
- package/dist/src/validator/session-validator.d.ts.map +1 -0
- package/dist/src/validator/session-validator.js +280 -0
- package/dist/tests/integration/round-trip.test.d.ts +5 -0
- package/dist/tests/integration/round-trip.test.d.ts.map +1 -0
- package/dist/tests/integration/round-trip.test.js +320 -0
- package/dist/tests/integration/voip-examples.test.d.ts +5 -0
- package/dist/tests/integration/voip-examples.test.d.ts.map +1 -0
- package/dist/tests/integration/voip-examples.test.js +361 -0
- package/dist/tests/unit/builder/media-builder.test.d.ts +5 -0
- package/dist/tests/unit/builder/media-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/builder/media-builder.test.js +524 -0
- package/dist/tests/unit/builder/session-builder.test.d.ts +5 -0
- package/dist/tests/unit/builder/session-builder.test.d.ts.map +1 -0
- package/dist/tests/unit/builder/session-builder.test.js +367 -0
- package/dist/tests/unit/parser/attribute-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/attribute-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/attribute-parser.test.js +319 -0
- package/dist/tests/unit/parser/field-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/field-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/field-parser.test.js +355 -0
- package/dist/tests/unit/parser/media-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/media-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/media-parser.test.js +241 -0
- package/dist/tests/unit/parser/primitive-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/primitive-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/primitive-parser.test.js +261 -0
- package/dist/tests/unit/parser/scanner.test.d.ts +5 -0
- package/dist/tests/unit/parser/scanner.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/scanner.test.js +241 -0
- package/dist/tests/unit/parser/session-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/session-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/session-parser.test.js +346 -0
- package/dist/tests/unit/parser/time-parser.test.d.ts +5 -0
- package/dist/tests/unit/parser/time-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/parser/time-parser.test.js +173 -0
- package/dist/tests/unit/serializer/attribute-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/attribute-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/attribute-serializer.test.js +78 -0
- package/dist/tests/unit/serializer/field-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/field-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/field-serializer.test.js +159 -0
- package/dist/tests/unit/serializer/media-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/media-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/media-serializer.test.js +155 -0
- package/dist/tests/unit/serializer/session-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/session-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/session-serializer.test.js +317 -0
- package/dist/tests/unit/serializer/time-serializer.test.d.ts +5 -0
- package/dist/tests/unit/serializer/time-serializer.test.d.ts.map +1 -0
- package/dist/tests/unit/serializer/time-serializer.test.js +115 -0
- package/dist/tests/unit/types/errors.test.d.ts +5 -0
- package/dist/tests/unit/types/errors.test.d.ts.map +1 -0
- package/dist/tests/unit/types/errors.test.js +127 -0
- package/dist/tests/unit/types/network.test.d.ts +5 -0
- package/dist/tests/unit/types/network.test.d.ts.map +1 -0
- package/dist/tests/unit/types/network.test.js +132 -0
- package/dist/tests/unit/types/primitives.test.d.ts +5 -0
- package/dist/tests/unit/types/primitives.test.d.ts.map +1 -0
- package/dist/tests/unit/types/primitives.test.js +108 -0
- package/dist/tests/unit/utils/address-parser.test.d.ts +5 -0
- package/dist/tests/unit/utils/address-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/address-parser.test.js +203 -0
- package/dist/tests/unit/utils/format-validators.test.d.ts +5 -0
- package/dist/tests/unit/utils/format-validators.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/format-validators.test.js +224 -0
- package/dist/tests/unit/utils/line-reader.test.d.ts +5 -0
- package/dist/tests/unit/utils/line-reader.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/line-reader.test.js +157 -0
- package/dist/tests/unit/utils/time-converter.test.d.ts +5 -0
- package/dist/tests/unit/utils/time-converter.test.d.ts.map +1 -0
- package/dist/tests/unit/utils/time-converter.test.js +190 -0
- package/dist/tests/unit/validator/media-validator.test.d.ts +5 -0
- package/dist/tests/unit/validator/media-validator.test.d.ts.map +1 -0
- package/dist/tests/unit/validator/media-validator.test.js +313 -0
- package/dist/tests/unit/validator/semantic-validator.test.d.ts +5 -0
- package/dist/tests/unit/validator/semantic-validator.test.d.ts.map +1 -0
- package/dist/tests/unit/validator/semantic-validator.test.js +262 -0
- package/dist/tests/unit/validator/session-validator.test.d.ts +5 -0
- package/dist/tests/unit/validator/session-validator.test.d.ts.map +1 -0
- package/dist/tests/unit/validator/session-validator.test.js +447 -0
- package/package.json +50 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for media-builder.ts
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const media_builder_1 = require("../../../src/builder/media-builder");
|
|
7
|
+
const errors_1 = require("../../../src/types/errors");
|
|
8
|
+
describe('media-builder', () => {
|
|
9
|
+
describe('MediaBuilder', () => {
|
|
10
|
+
describe('required fields', () => {
|
|
11
|
+
it('should throw when type is missing', () => {
|
|
12
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
13
|
+
.port(49170)
|
|
14
|
+
.protocol('RTP/AVP')
|
|
15
|
+
.formats(['0']);
|
|
16
|
+
expect(() => builder.build()).toThrow(errors_1.BuilderError);
|
|
17
|
+
expect(() => builder.build()).toThrow('media type');
|
|
18
|
+
});
|
|
19
|
+
it('should throw when port is missing', () => {
|
|
20
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
21
|
+
.type('audio')
|
|
22
|
+
.protocol('RTP/AVP')
|
|
23
|
+
.formats(['0']);
|
|
24
|
+
expect(() => builder.build()).toThrow(errors_1.BuilderError);
|
|
25
|
+
expect(() => builder.build()).toThrow('port');
|
|
26
|
+
});
|
|
27
|
+
it('should throw when protocol is missing', () => {
|
|
28
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
29
|
+
.type('audio')
|
|
30
|
+
.port(49170)
|
|
31
|
+
.formats(['0']);
|
|
32
|
+
expect(() => builder.build()).toThrow(errors_1.BuilderError);
|
|
33
|
+
expect(() => builder.build()).toThrow('protocol');
|
|
34
|
+
});
|
|
35
|
+
it('should throw when formats is empty', () => {
|
|
36
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
37
|
+
.type('audio')
|
|
38
|
+
.port(49170)
|
|
39
|
+
.protocol('RTP/AVP');
|
|
40
|
+
expect(() => builder.build()).toThrow(errors_1.BuilderError);
|
|
41
|
+
expect(() => builder.build()).toThrow('formats');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('minimal media', () => {
|
|
45
|
+
it('should build minimal audio media', () => {
|
|
46
|
+
const media = new media_builder_1.MediaBuilder()
|
|
47
|
+
.type('audio')
|
|
48
|
+
.port(49170)
|
|
49
|
+
.protocol('RTP/AVP')
|
|
50
|
+
.formats(['0'])
|
|
51
|
+
.build();
|
|
52
|
+
expect(media.media.type).toBe('audio');
|
|
53
|
+
expect(media.media.port).toEqual({ kind: 'simple', value: 49170 });
|
|
54
|
+
expect(media.media.proto).toBe('RTP/AVP');
|
|
55
|
+
expect(media.media.formats).toEqual(['0']);
|
|
56
|
+
});
|
|
57
|
+
it('should build minimal video media', () => {
|
|
58
|
+
const media = new media_builder_1.MediaBuilder()
|
|
59
|
+
.type('video')
|
|
60
|
+
.port(51372)
|
|
61
|
+
.protocol('RTP/AVP')
|
|
62
|
+
.formats(['96'])
|
|
63
|
+
.build();
|
|
64
|
+
expect(media.media.type).toBe('video');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('port options', () => {
|
|
68
|
+
it('should set simple port', () => {
|
|
69
|
+
const media = new media_builder_1.MediaBuilder()
|
|
70
|
+
.type('audio')
|
|
71
|
+
.port(49170)
|
|
72
|
+
.protocol('RTP/AVP')
|
|
73
|
+
.formats(['0'])
|
|
74
|
+
.build();
|
|
75
|
+
expect(media.media.port).toEqual({ kind: 'simple', value: 49170 });
|
|
76
|
+
});
|
|
77
|
+
it('should set port range', () => {
|
|
78
|
+
const media = new media_builder_1.MediaBuilder()
|
|
79
|
+
.type('audio')
|
|
80
|
+
.portRange(49170, 2)
|
|
81
|
+
.protocol('RTP/AVP')
|
|
82
|
+
.formats(['0'])
|
|
83
|
+
.build();
|
|
84
|
+
expect(media.media.port).toEqual({ kind: 'range', base: 49170, count: 2 });
|
|
85
|
+
});
|
|
86
|
+
it('should set disabled port (0)', () => {
|
|
87
|
+
const media = new media_builder_1.MediaBuilder()
|
|
88
|
+
.type('audio')
|
|
89
|
+
.disabled()
|
|
90
|
+
.protocol('RTP/AVP')
|
|
91
|
+
.formats(['0'])
|
|
92
|
+
.build();
|
|
93
|
+
expect(media.media.port).toEqual({ kind: 'simple', value: 0 });
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe('formats', () => {
|
|
97
|
+
it('should set multiple formats at once', () => {
|
|
98
|
+
const media = new media_builder_1.MediaBuilder()
|
|
99
|
+
.type('audio')
|
|
100
|
+
.port(49170)
|
|
101
|
+
.protocol('RTP/AVP')
|
|
102
|
+
.formats(['0', '8', '96'])
|
|
103
|
+
.build();
|
|
104
|
+
expect(media.media.formats).toEqual(['0', '8', '96']);
|
|
105
|
+
});
|
|
106
|
+
it('should add formats one by one', () => {
|
|
107
|
+
const media = new media_builder_1.MediaBuilder()
|
|
108
|
+
.type('audio')
|
|
109
|
+
.port(49170)
|
|
110
|
+
.protocol('RTP/AVP')
|
|
111
|
+
.addFormat('0')
|
|
112
|
+
.addFormat('8')
|
|
113
|
+
.build();
|
|
114
|
+
expect(media.media.formats).toEqual(['0', '8']);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe('information', () => {
|
|
118
|
+
it('should set media information', () => {
|
|
119
|
+
const media = new media_builder_1.MediaBuilder()
|
|
120
|
+
.type('audio')
|
|
121
|
+
.port(49170)
|
|
122
|
+
.protocol('RTP/AVP')
|
|
123
|
+
.formats(['0'])
|
|
124
|
+
.information('Audio stream')
|
|
125
|
+
.build();
|
|
126
|
+
expect(media.information).toBe('Audio stream');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe('connection', () => {
|
|
130
|
+
it('should add IPv4 connection', () => {
|
|
131
|
+
const media = new media_builder_1.MediaBuilder()
|
|
132
|
+
.type('audio')
|
|
133
|
+
.port(49170)
|
|
134
|
+
.protocol('RTP/AVP')
|
|
135
|
+
.formats(['0'])
|
|
136
|
+
.connection('192.168.1.100')
|
|
137
|
+
.build();
|
|
138
|
+
expect(media.connections).toHaveLength(1);
|
|
139
|
+
expect(media.connections[0].addrType).toBe('IP4');
|
|
140
|
+
});
|
|
141
|
+
it('should add IPv6 connection', () => {
|
|
142
|
+
const media = new media_builder_1.MediaBuilder()
|
|
143
|
+
.type('audio')
|
|
144
|
+
.port(49170)
|
|
145
|
+
.protocol('RTP/AVP')
|
|
146
|
+
.formats(['0'])
|
|
147
|
+
.connection('2001:db8::1')
|
|
148
|
+
.build();
|
|
149
|
+
expect(media.connections[0].addrType).toBe('IP6');
|
|
150
|
+
});
|
|
151
|
+
it('should add multiple connections', () => {
|
|
152
|
+
const media = new media_builder_1.MediaBuilder()
|
|
153
|
+
.type('audio')
|
|
154
|
+
.port(49170)
|
|
155
|
+
.protocol('RTP/AVP')
|
|
156
|
+
.formats(['0'])
|
|
157
|
+
.connection('192.168.1.100')
|
|
158
|
+
.connection('192.168.1.101')
|
|
159
|
+
.build();
|
|
160
|
+
expect(media.connections).toHaveLength(2);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('bandwidth', () => {
|
|
164
|
+
it('should add AS bandwidth with shorthand', () => {
|
|
165
|
+
const media = new media_builder_1.MediaBuilder()
|
|
166
|
+
.type('audio')
|
|
167
|
+
.port(49170)
|
|
168
|
+
.protocol('RTP/AVP')
|
|
169
|
+
.formats(['0'])
|
|
170
|
+
.bandwidth(128)
|
|
171
|
+
.build();
|
|
172
|
+
expect(media.bandwidths).toHaveLength(1);
|
|
173
|
+
expect(media.bandwidths[0].type).toBe('AS');
|
|
174
|
+
expect(media.bandwidths[0].value).toBe(128);
|
|
175
|
+
});
|
|
176
|
+
it('should add bandwidth with explicit type', () => {
|
|
177
|
+
const media = new media_builder_1.MediaBuilder()
|
|
178
|
+
.type('audio')
|
|
179
|
+
.port(49170)
|
|
180
|
+
.protocol('RTP/AVP')
|
|
181
|
+
.formats(['0'])
|
|
182
|
+
.addBandwidth('CT', 256)
|
|
183
|
+
.build();
|
|
184
|
+
expect(media.bandwidths[0].type).toBe('CT');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
describe('key', () => {
|
|
188
|
+
it('should set encryption key', () => {
|
|
189
|
+
const media = new media_builder_1.MediaBuilder()
|
|
190
|
+
.type('audio')
|
|
191
|
+
.port(49170)
|
|
192
|
+
.protocol('RTP/AVP')
|
|
193
|
+
.formats(['0'])
|
|
194
|
+
.key('clear:testkey')
|
|
195
|
+
.build();
|
|
196
|
+
expect(media.key).toBe('clear:testkey');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
describe('direction attributes', () => {
|
|
200
|
+
it('should add sendrecv', () => {
|
|
201
|
+
const media = new media_builder_1.MediaBuilder()
|
|
202
|
+
.type('audio')
|
|
203
|
+
.port(49170)
|
|
204
|
+
.protocol('RTP/AVP')
|
|
205
|
+
.formats(['0'])
|
|
206
|
+
.sendrecv()
|
|
207
|
+
.build();
|
|
208
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'sendrecv' });
|
|
209
|
+
});
|
|
210
|
+
it('should add recvonly', () => {
|
|
211
|
+
const media = new media_builder_1.MediaBuilder()
|
|
212
|
+
.type('audio')
|
|
213
|
+
.port(49170)
|
|
214
|
+
.protocol('RTP/AVP')
|
|
215
|
+
.formats(['0'])
|
|
216
|
+
.recvonly()
|
|
217
|
+
.build();
|
|
218
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'recvonly' });
|
|
219
|
+
});
|
|
220
|
+
it('should add sendonly', () => {
|
|
221
|
+
const media = new media_builder_1.MediaBuilder()
|
|
222
|
+
.type('audio')
|
|
223
|
+
.port(49170)
|
|
224
|
+
.protocol('RTP/AVP')
|
|
225
|
+
.formats(['0'])
|
|
226
|
+
.sendonly()
|
|
227
|
+
.build();
|
|
228
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'sendonly' });
|
|
229
|
+
});
|
|
230
|
+
it('should add inactive', () => {
|
|
231
|
+
const media = new media_builder_1.MediaBuilder()
|
|
232
|
+
.type('audio')
|
|
233
|
+
.port(49170)
|
|
234
|
+
.protocol('RTP/AVP')
|
|
235
|
+
.formats(['0'])
|
|
236
|
+
.inactive()
|
|
237
|
+
.build();
|
|
238
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'inactive' });
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
describe('RTP attributes', () => {
|
|
242
|
+
it('should add rtpmap', () => {
|
|
243
|
+
const media = new media_builder_1.MediaBuilder()
|
|
244
|
+
.type('audio')
|
|
245
|
+
.port(49170)
|
|
246
|
+
.protocol('RTP/AVP')
|
|
247
|
+
.formats(['0', '8'])
|
|
248
|
+
.rtpmap(0, 'PCMU', 8000)
|
|
249
|
+
.rtpmap(8, 'PCMA', 8000)
|
|
250
|
+
.build();
|
|
251
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'rtpmap', value: '0 PCMU/8000' });
|
|
252
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'rtpmap', value: '8 PCMA/8000' });
|
|
253
|
+
});
|
|
254
|
+
it('should add rtpmap with encoding params', () => {
|
|
255
|
+
const media = new media_builder_1.MediaBuilder()
|
|
256
|
+
.type('audio')
|
|
257
|
+
.port(49170)
|
|
258
|
+
.protocol('RTP/AVP')
|
|
259
|
+
.formats(['96'])
|
|
260
|
+
.rtpmap(96, 'opus', 48000, 2)
|
|
261
|
+
.build();
|
|
262
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'rtpmap', value: '96 opus/48000/2' });
|
|
263
|
+
});
|
|
264
|
+
it('should add fmtp', () => {
|
|
265
|
+
const media = new media_builder_1.MediaBuilder()
|
|
266
|
+
.type('video')
|
|
267
|
+
.port(51372)
|
|
268
|
+
.protocol('RTP/AVP')
|
|
269
|
+
.formats(['96'])
|
|
270
|
+
.fmtp(96, 'profile-level-id=42e01f')
|
|
271
|
+
.build();
|
|
272
|
+
expect(media.attributes).toContainEqual({
|
|
273
|
+
kind: 'value',
|
|
274
|
+
name: 'fmtp',
|
|
275
|
+
value: '96 profile-level-id=42e01f',
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
it('should add ptime', () => {
|
|
279
|
+
const media = new media_builder_1.MediaBuilder()
|
|
280
|
+
.type('audio')
|
|
281
|
+
.port(49170)
|
|
282
|
+
.protocol('RTP/AVP')
|
|
283
|
+
.formats(['0'])
|
|
284
|
+
.ptime(20)
|
|
285
|
+
.build();
|
|
286
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'ptime', value: '20' });
|
|
287
|
+
});
|
|
288
|
+
it('should add maxptime', () => {
|
|
289
|
+
const media = new media_builder_1.MediaBuilder()
|
|
290
|
+
.type('audio')
|
|
291
|
+
.port(49170)
|
|
292
|
+
.protocol('RTP/AVP')
|
|
293
|
+
.formats(['0'])
|
|
294
|
+
.maxptime(60)
|
|
295
|
+
.build();
|
|
296
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'maxptime', value: '60' });
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
describe('video attributes', () => {
|
|
300
|
+
it('should add framerate', () => {
|
|
301
|
+
const media = new media_builder_1.MediaBuilder()
|
|
302
|
+
.type('video')
|
|
303
|
+
.port(51372)
|
|
304
|
+
.protocol('RTP/AVP')
|
|
305
|
+
.formats(['96'])
|
|
306
|
+
.framerate(30)
|
|
307
|
+
.build();
|
|
308
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'framerate', value: '30' });
|
|
309
|
+
});
|
|
310
|
+
it('should add quality', () => {
|
|
311
|
+
const media = new media_builder_1.MediaBuilder()
|
|
312
|
+
.type('video')
|
|
313
|
+
.port(51372)
|
|
314
|
+
.protocol('RTP/AVP')
|
|
315
|
+
.formats(['96'])
|
|
316
|
+
.quality(5)
|
|
317
|
+
.build();
|
|
318
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'quality', value: '5' });
|
|
319
|
+
});
|
|
320
|
+
it('should throw for quality out of range', () => {
|
|
321
|
+
const builder = new media_builder_1.MediaBuilder()
|
|
322
|
+
.type('video')
|
|
323
|
+
.port(51372)
|
|
324
|
+
.protocol('RTP/AVP')
|
|
325
|
+
.formats(['96']);
|
|
326
|
+
expect(() => builder.quality(11)).toThrow(errors_1.BuilderError);
|
|
327
|
+
expect(() => builder.quality(-1)).toThrow(errors_1.BuilderError);
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
describe('WebRTC attributes', () => {
|
|
331
|
+
it('should add mid', () => {
|
|
332
|
+
const media = new media_builder_1.MediaBuilder()
|
|
333
|
+
.type('audio')
|
|
334
|
+
.port(49170)
|
|
335
|
+
.protocol('RTP/AVP')
|
|
336
|
+
.formats(['0'])
|
|
337
|
+
.mid('audio')
|
|
338
|
+
.build();
|
|
339
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'mid', value: 'audio' });
|
|
340
|
+
});
|
|
341
|
+
it('should add ice-ufrag', () => {
|
|
342
|
+
const media = new media_builder_1.MediaBuilder()
|
|
343
|
+
.type('audio')
|
|
344
|
+
.port(49170)
|
|
345
|
+
.protocol('RTP/AVP')
|
|
346
|
+
.formats(['0'])
|
|
347
|
+
.iceUfrag('a1b2c3d4')
|
|
348
|
+
.build();
|
|
349
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'ice-ufrag', value: 'a1b2c3d4' });
|
|
350
|
+
});
|
|
351
|
+
it('should add ice-pwd', () => {
|
|
352
|
+
const media = new media_builder_1.MediaBuilder()
|
|
353
|
+
.type('audio')
|
|
354
|
+
.port(49170)
|
|
355
|
+
.protocol('RTP/AVP')
|
|
356
|
+
.formats(['0'])
|
|
357
|
+
.icePwd('password123')
|
|
358
|
+
.build();
|
|
359
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'ice-pwd', value: 'password123' });
|
|
360
|
+
});
|
|
361
|
+
it('should add fingerprint', () => {
|
|
362
|
+
const media = new media_builder_1.MediaBuilder()
|
|
363
|
+
.type('audio')
|
|
364
|
+
.port(49170)
|
|
365
|
+
.protocol('RTP/AVP')
|
|
366
|
+
.formats(['0'])
|
|
367
|
+
.fingerprint('sha-256', 'AB:CD:EF:12:34')
|
|
368
|
+
.build();
|
|
369
|
+
expect(media.attributes).toContainEqual({
|
|
370
|
+
kind: 'value',
|
|
371
|
+
name: 'fingerprint',
|
|
372
|
+
value: 'sha-256 AB:CD:EF:12:34',
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
it('should add setup', () => {
|
|
376
|
+
const media = new media_builder_1.MediaBuilder()
|
|
377
|
+
.type('audio')
|
|
378
|
+
.port(49170)
|
|
379
|
+
.protocol('RTP/AVP')
|
|
380
|
+
.formats(['0'])
|
|
381
|
+
.setup('actpass')
|
|
382
|
+
.build();
|
|
383
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'setup', value: 'actpass' });
|
|
384
|
+
});
|
|
385
|
+
it('should add rtcp', () => {
|
|
386
|
+
const media = new media_builder_1.MediaBuilder()
|
|
387
|
+
.type('audio')
|
|
388
|
+
.port(49170)
|
|
389
|
+
.protocol('RTP/AVP')
|
|
390
|
+
.formats(['0'])
|
|
391
|
+
.rtcp(49171)
|
|
392
|
+
.build();
|
|
393
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'rtcp', value: '49171' });
|
|
394
|
+
});
|
|
395
|
+
it('should add rtcp with address', () => {
|
|
396
|
+
const media = new media_builder_1.MediaBuilder()
|
|
397
|
+
.type('audio')
|
|
398
|
+
.port(49170)
|
|
399
|
+
.protocol('RTP/AVP')
|
|
400
|
+
.formats(['0'])
|
|
401
|
+
.rtcp(49171, '192.168.1.100')
|
|
402
|
+
.build();
|
|
403
|
+
expect(media.attributes).toContainEqual({
|
|
404
|
+
kind: 'value',
|
|
405
|
+
name: 'rtcp',
|
|
406
|
+
value: '49171 IN IP4 192.168.1.100',
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
it('should add rtcp-mux', () => {
|
|
410
|
+
const media = new media_builder_1.MediaBuilder()
|
|
411
|
+
.type('audio')
|
|
412
|
+
.port(49170)
|
|
413
|
+
.protocol('RTP/AVP')
|
|
414
|
+
.formats(['0'])
|
|
415
|
+
.rtcpMux()
|
|
416
|
+
.build();
|
|
417
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'rtcp-mux' });
|
|
418
|
+
});
|
|
419
|
+
it('should add rtcp-rsize', () => {
|
|
420
|
+
const media = new media_builder_1.MediaBuilder()
|
|
421
|
+
.type('audio')
|
|
422
|
+
.port(49170)
|
|
423
|
+
.protocol('RTP/AVP')
|
|
424
|
+
.formats(['0'])
|
|
425
|
+
.rtcpRsize()
|
|
426
|
+
.build();
|
|
427
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'rtcp-rsize' });
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
describe('custom attributes', () => {
|
|
431
|
+
it('should add custom property attribute', () => {
|
|
432
|
+
const media = new media_builder_1.MediaBuilder()
|
|
433
|
+
.type('audio')
|
|
434
|
+
.port(49170)
|
|
435
|
+
.protocol('RTP/AVP')
|
|
436
|
+
.formats(['0'])
|
|
437
|
+
.addPropertyAttribute('custom-prop')
|
|
438
|
+
.build();
|
|
439
|
+
expect(media.attributes).toContainEqual({ kind: 'property', name: 'custom-prop' });
|
|
440
|
+
});
|
|
441
|
+
it('should add custom value attribute', () => {
|
|
442
|
+
const media = new media_builder_1.MediaBuilder()
|
|
443
|
+
.type('audio')
|
|
444
|
+
.port(49170)
|
|
445
|
+
.protocol('RTP/AVP')
|
|
446
|
+
.formats(['0'])
|
|
447
|
+
.addValueAttribute('custom', 'value')
|
|
448
|
+
.build();
|
|
449
|
+
expect(media.attributes).toContainEqual({ kind: 'value', name: 'custom', value: 'value' });
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
describe('factory functions', () => {
|
|
454
|
+
it('mediaBuilder should create a new MediaBuilder', () => {
|
|
455
|
+
const builder = (0, media_builder_1.mediaBuilder)();
|
|
456
|
+
expect(builder).toBeInstanceOf(media_builder_1.MediaBuilder);
|
|
457
|
+
});
|
|
458
|
+
it('audioBuilder should create pre-configured audio builder', () => {
|
|
459
|
+
const builder = (0, media_builder_1.audioBuilder)();
|
|
460
|
+
const media = builder
|
|
461
|
+
.port(49170)
|
|
462
|
+
.protocol('RTP/AVP')
|
|
463
|
+
.formats(['0'])
|
|
464
|
+
.build();
|
|
465
|
+
expect(media.media.type).toBe('audio');
|
|
466
|
+
});
|
|
467
|
+
it('videoBuilder should create pre-configured video builder', () => {
|
|
468
|
+
const builder = (0, media_builder_1.videoBuilder)();
|
|
469
|
+
const media = builder
|
|
470
|
+
.port(51372)
|
|
471
|
+
.protocol('RTP/AVP')
|
|
472
|
+
.formats(['96'])
|
|
473
|
+
.build();
|
|
474
|
+
expect(media.media.type).toBe('video');
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
describe('complete media example', () => {
|
|
478
|
+
it('should build complete audio media with all common attributes', () => {
|
|
479
|
+
const media = new media_builder_1.MediaBuilder()
|
|
480
|
+
.type('audio')
|
|
481
|
+
.port(49170)
|
|
482
|
+
.protocol('RTP/SAVPF')
|
|
483
|
+
.formats(['0', '8', '96'])
|
|
484
|
+
.connection('192.168.1.100')
|
|
485
|
+
.bandwidth(128)
|
|
486
|
+
.rtpmap(0, 'PCMU', 8000)
|
|
487
|
+
.rtpmap(8, 'PCMA', 8000)
|
|
488
|
+
.rtpmap(96, 'opus', 48000, 2)
|
|
489
|
+
.fmtp(96, 'minptime=10;useinbandfec=1')
|
|
490
|
+
.ptime(20)
|
|
491
|
+
.maxptime(60)
|
|
492
|
+
.mid('audio')
|
|
493
|
+
.sendrecv()
|
|
494
|
+
.rtcpMux()
|
|
495
|
+
.build();
|
|
496
|
+
expect(media.media.type).toBe('audio');
|
|
497
|
+
expect(media.media.formats).toHaveLength(3);
|
|
498
|
+
expect(media.connections).toHaveLength(1);
|
|
499
|
+
expect(media.bandwidths).toHaveLength(1);
|
|
500
|
+
expect(media.attributes.length).toBeGreaterThan(5);
|
|
501
|
+
});
|
|
502
|
+
it('should build complete video media with all common attributes', () => {
|
|
503
|
+
const media = new media_builder_1.MediaBuilder()
|
|
504
|
+
.type('video')
|
|
505
|
+
.port(51372)
|
|
506
|
+
.protocol('RTP/SAVPF')
|
|
507
|
+
.formats(['96', '97'])
|
|
508
|
+
.connection('192.168.1.100')
|
|
509
|
+
.bandwidth(1000)
|
|
510
|
+
.rtpmap(96, 'VP8', 90000)
|
|
511
|
+
.rtpmap(97, 'H264', 90000)
|
|
512
|
+
.fmtp(97, 'profile-level-id=42e01f;packetization-mode=1')
|
|
513
|
+
.framerate(30)
|
|
514
|
+
.mid('video')
|
|
515
|
+
.sendrecv()
|
|
516
|
+
.rtcpMux()
|
|
517
|
+
.rtcpRsize()
|
|
518
|
+
.build();
|
|
519
|
+
expect(media.media.type).toBe('video');
|
|
520
|
+
expect(media.media.formats).toHaveLength(2);
|
|
521
|
+
expect(media.attributes.length).toBeGreaterThan(5);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-builder.test.d.ts","sourceRoot":"","sources":["../../../../tests/unit/builder/session-builder.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|