From c84da04f05624f4c3061357fd6caa229bd5e873d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 21 Nov 2022 11:42:00 +0100 Subject: [PATCH] Migrate Node tests to TypeScript (#958) --- .gitattributes | 1 - .github/workflows/mediasoup-node.yaml | 3 +- .gitignore | 1 + CHANGELOG.md | 1 + node/.eslintrc.js | 11 +- node/{ => src}/tests/data/dtls-cert.pem | 0 node/{ => src}/tests/data/dtls-key.pem | 0 .../tests/test-ActiveSpeakerObserver.ts} | 22 +- .../tests/test-AudioLevelObserver.ts} | 22 +- .../tests/test-Consumer.ts} | 109 ++-- .../tests/test-DataConsumer.ts} | 46 +- .../tests/test-DataProducer.ts} | 49 +- .../tests/test-DirectTransport.ts} | 33 +- .../tests/test-PipeTransport.ts} | 141 +++--- .../tests/test-PlainTransport.ts} | 88 ++-- .../tests/test-Producer.ts} | 62 ++- .../tests/test-Router.ts} | 24 +- .../tests/test-WebRtcServer.ts} | 28 +- .../tests/test-WebRtcTransport.ts} | 77 +-- .../tests/test-Worker.ts} | 39 +- .../tests/test-mediasoup.ts} | 19 +- .../tests/test-multiopus.ts} | 29 +- .../tests/test-node-sctp.ts} | 58 ++- .../test-ortc.js => src/tests/test-ortc.ts} | 90 ++-- npm-scripts.js | 51 +- package-lock.json | 479 ++++++------------ package.json | 10 +- 27 files changed, 693 insertions(+), 800 deletions(-) rename node/{ => src}/tests/data/dtls-cert.pem (100%) rename node/{ => src}/tests/data/dtls-key.pem (100%) rename node/{tests/test-ActiveSpeakerObserver.js => src/tests/test-ActiveSpeakerObserver.ts} (87%) rename node/{tests/test-AudioLevelObserver.js => src/tests/test-AudioLevelObserver.ts} (88%) rename node/{tests/test-Consumer.js => src/tests/test-Consumer.ts} (89%) rename node/{tests/test-DataConsumer.js => src/tests/test-DataConsumer.ts} (85%) rename node/{tests/test-DataProducer.js => src/tests/test-DataProducer.ts} (83%) rename node/{tests/test-DirectTransport.js => src/tests/test-DirectTransport.ts} (91%) rename node/{tests/test-PipeTransport.js => src/tests/test-PipeTransport.ts} (85%) rename node/{tests/test-PlainTransport.js => src/tests/test-PlainTransport.ts} (83%) rename node/{tests/test-Producer.js => src/tests/test-Producer.ts} (91%) rename node/{tests/test-Router.js => src/tests/test-Router.ts} (87%) rename node/{tests/test-WebRtcServer.js => src/tests/test-WebRtcServer.ts} (96%) rename node/{tests/test-WebRtcTransport.js => src/tests/test-WebRtcTransport.ts} (89%) rename node/{tests/test-Worker.js => src/tests/test-Worker.ts} (90%) rename node/{tests/test-mediasoup.js => src/tests/test-mediasoup.ts} (80%) rename node/{tests/test-multiopus.js => src/tests/test-multiopus.ts} (88%) rename node/{tests/test-node-sctp.js => src/tests/test-node-sctp.ts} (81%) rename node/{tests/test-ortc.js => src/tests/test-ortc.ts} (81%) diff --git a/.gitattributes b/.gitattributes index 49ac7d6723c..7d71e26df01 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,6 @@ # Tell GitHub to ignore some folders when detecting the project language. art/* linguist-vendored=true doc/* linguist-vendored=true -node/test/* linguist-vendored=true rust/benches/* linguist-vendored=true rust/examples/* linguist-vendored=true rust/examples-frontend/* linguist-vendored=true diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 521d47598c0..7e3292eadbe 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -38,7 +38,6 @@ jobs: restore-keys: | ${{ matrix.ci.os }}-node- - - run: npm install + - run: npm ci - run: npm run lint:node - if: runner.os == 'Linux' - run: npm run test:node diff --git a/.gitignore b/.gitignore index 53cdc08ab46..21df911a661 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ ## Others. /coverage +/.cache /NO_GIT *.swp *.swo diff --git a/CHANGELOG.md b/CHANGELOG.md index a259979d91c..2335cd7f9d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT +* Node: Migrate tests to TypeScript (PR #958). * Node: Remove compiled JavaScript from repository and compile TypeScript code on NPM `prepare` script on demand when installed via git (PR #954). * `Worker`: Add `RTC::Shared` singleton for RTC entities (PR #953). diff --git a/node/.eslintrc.js b/node/.eslintrc.js index b844b5faa60..93d91a46550 100644 --- a/node/.eslintrc.js +++ b/node/.eslintrc.js @@ -1,3 +1,7 @@ +const os = require('os'); + +const isWindows = os.platform() === 'win32'; + const eslintConfig = { env : @@ -15,7 +19,8 @@ const eslintConfig = { impliedStrict : true }, - lib : [ 'es2018' ] + lib : [ 'es2018' ], + project : 'node/tsconfig.json' }, globals : { @@ -59,7 +64,7 @@ const eslintConfig = } ], 'keyword-spacing' : 2, - 'linebreak-style' : [ 2, 'unix' ], + 'linebreak-style' : [ 2, isWindows ? 'windows' : 'unix' ], 'lines-around-comment' : [ 2, { allowBlockStart : true, @@ -222,7 +227,7 @@ eslintConfig.overrides.push( eslintConfig.overrides.push( { - files : [ '*.js' ], + files : [ '*.ts' ], env : { ...eslintConfig.env, 'jest/globals' : true diff --git a/node/tests/data/dtls-cert.pem b/node/src/tests/data/dtls-cert.pem similarity index 100% rename from node/tests/data/dtls-cert.pem rename to node/src/tests/data/dtls-cert.pem diff --git a/node/tests/data/dtls-key.pem b/node/src/tests/data/dtls-key.pem similarity index 100% rename from node/tests/data/dtls-key.pem rename to node/src/tests/data/dtls-key.pem diff --git a/node/tests/test-ActiveSpeakerObserver.js b/node/src/tests/test-ActiveSpeakerObserver.ts similarity index 87% rename from node/tests/test-ActiveSpeakerObserver.js rename to node/src/tests/test-ActiveSpeakerObserver.ts index a00d5ef5f13..248b8bf0d5c 100644 --- a/node/tests/test-ActiveSpeakerObserver.js +++ b/node/src/tests/test-ActiveSpeakerObserver.ts @@ -1,14 +1,12 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let activeSpeakerObserver; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let activeSpeakerObserver: mediasoup.types.ActiveSpeakerObserver; -const mediaCodecs = +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -41,7 +39,7 @@ test('router.createActiveSpeakerObserver() succeeds', async () => expect(onObserverNewRtpObserver).toHaveBeenCalledTimes(1); expect(onObserverNewRtpObserver).toHaveBeenCalledWith(activeSpeakerObserver); - expect(activeSpeakerObserver.id).toBeType('string'); + expect(typeof activeSpeakerObserver.id).toBe('string'); expect(activeSpeakerObserver.closed).toBe(false); expect(activeSpeakerObserver.paused).toBe(false); expect(activeSpeakerObserver.appData).toEqual({}); @@ -56,10 +54,12 @@ test('router.createActiveSpeakerObserver() succeeds', async () => test('router.createActiveSpeakerObserver() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(router.createActiveSpeakerObserver({ interval: false })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createActiveSpeakerObserver({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); @@ -102,7 +102,7 @@ test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () = const router2 = await worker.createRouter({ mediaCodecs }); const activeSpeakerObserver2 = await router2.createAudioLevelObserver(); - await new Promise((resolve) => + await new Promise((resolve) => { activeSpeakerObserver2.on('routerclose', resolve); router2.close(); @@ -113,7 +113,7 @@ test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () = test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => { - await new Promise((resolve) => + await new Promise((resolve) => { activeSpeakerObserver.on('routerclose', resolve); worker.close(); diff --git a/node/tests/test-AudioLevelObserver.js b/node/src/tests/test-AudioLevelObserver.ts similarity index 88% rename from node/tests/test-AudioLevelObserver.js rename to node/src/tests/test-AudioLevelObserver.ts index 7bbd1016701..cc8155e3a54 100644 --- a/node/tests/test-AudioLevelObserver.js +++ b/node/src/tests/test-AudioLevelObserver.ts @@ -1,14 +1,11 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); +import * as mediasoup from '../'; const { createWorker } = mediasoup; -expect.extend({ toBeType }); +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let audioLevelObserver: mediasoup.types.AudioLevelObserver; -let worker; -let router; -let audioLevelObserver; - -const mediaCodecs = +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -41,7 +38,7 @@ test('router.createAudioLevelObserver() succeeds', async () => expect(onObserverNewRtpObserver).toHaveBeenCalledTimes(1); expect(onObserverNewRtpObserver).toHaveBeenCalledWith(audioLevelObserver); - expect(audioLevelObserver.id).toBeType('string'); + expect(typeof audioLevelObserver.id).toBe('string'); expect(audioLevelObserver.closed).toBe(false); expect(audioLevelObserver.paused).toBe(false); expect(audioLevelObserver.appData).toEqual({}); @@ -64,14 +61,17 @@ test('router.createAudioLevelObserver() with wrong arguments rejects with TypeEr .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createAudioLevelObserver({ threshold: 'foo' })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createAudioLevelObserver({ interval: false })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createAudioLevelObserver({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); @@ -114,7 +114,7 @@ test('AudioLevelObserver emits "routerclose" if Router is closed', async () => const router2 = await worker.createRouter({ mediaCodecs }); const audioLevelObserver2 = await router2.createAudioLevelObserver(); - await new Promise((resolve) => + await new Promise((resolve) => { audioLevelObserver2.on('routerclose', resolve); router2.close(); @@ -125,7 +125,7 @@ test('AudioLevelObserver emits "routerclose" if Router is closed', async () => test('AudioLevelObserver emits "routerclose" if Worker is closed', async () => { - await new Promise((resolve) => + await new Promise((resolve) => { audioLevelObserver.on('routerclose', resolve); worker.close(); diff --git a/node/tests/test-Consumer.js b/node/src/tests/test-Consumer.ts similarity index 89% rename from node/tests/test-Consumer.js rename to node/src/tests/test-Consumer.ts index e97961ebf2e..bdee353a104 100644 --- a/node/tests/test-Consumer.js +++ b/node/src/tests/test-Consumer.ts @@ -1,21 +1,19 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; -const { UnsupportedError } = require('../lib/errors'); - -expect.extend({ toBeType }); +import * as mediasoup from '../'; +import { UnsupportedError } from '../errors'; -let worker; -let router; -let transport1; -let transport2; -let audioProducer; -let videoProducer; -let audioConsumer; -let videoConsumer; -let videoPipeConsumer; +const { createWorker } = mediasoup; -const mediaCodecs = +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport1: mediasoup.types.WebRtcTransport; +let transport2: mediasoup.types.WebRtcTransport; +let audioProducer: mediasoup.types.Producer; +let videoProducer: mediasoup.types.Producer; +let audioConsumer: mediasoup.types.Consumer; +let videoConsumer: mediasoup.types.Consumer; +let videoPipeConsumer: mediasoup.types.Consumer; + +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -46,7 +44,7 @@ const mediaCodecs = } ]; -const audioProducerParameters = +const audioProducerParameters: mediasoup.types.ProducerOptions = { kind : 'audio', rtpParameters : @@ -88,7 +86,7 @@ const audioProducerParameters = appData : { foo: 1, bar: '2' } }; -const videoProducerParameters = +const videoProducerParameters: mediasoup.types.ProducerOptions = { kind : 'video', rtpParameters : @@ -145,7 +143,7 @@ const videoProducerParameters = appData : { foo: 1, bar: '2' } }; -const consumerDeviceCapabilities = +const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { codecs : [ @@ -283,11 +281,11 @@ test('transport.consume() succeeds', async () => expect(onObserverNewConsumer1).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer1).toHaveBeenCalledWith(audioConsumer); - expect(audioConsumer.id).toBeType('string'); + expect(typeof audioConsumer.id).toBe('string'); expect(audioConsumer.producerId).toBe(audioProducer.id); expect(audioConsumer.closed).toBe(false); expect(audioConsumer.kind).toBe('audio'); - expect(audioConsumer.rtpParameters).toBeType('object'); + expect(typeof audioConsumer.rtpParameters).toBe('object'); expect(audioConsumer.rtpParameters.mid).toBe('0'); expect(audioConsumer.rtpParameters.codecs.length).toBe(1); expect(audioConsumer.rtpParameters.codecs[0]).toEqual( @@ -354,11 +352,11 @@ test('transport.consume() succeeds', async () => expect(onObserverNewConsumer2).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer2).toHaveBeenCalledWith(videoConsumer); - expect(videoConsumer.id).toBeType('string'); + expect(typeof videoConsumer.id).toBe('string'); expect(videoConsumer.producerId).toBe(videoProducer.id); expect(videoConsumer.closed).toBe(false); expect(videoConsumer.kind).toBe('video'); - expect(videoConsumer.rtpParameters).toBeType('object'); + expect(typeof videoConsumer.rtpParameters).toBe('object'); expect(videoConsumer.rtpParameters.mid).toBe('1'); expect(videoConsumer.rtpParameters.codecs.length).toBe(2); expect(videoConsumer.rtpParameters.codecs[0]).toEqual( @@ -417,11 +415,11 @@ test('transport.consume() succeeds', async () => expect(onObserverNewConsumer3).toHaveBeenCalledTimes(1); expect(onObserverNewConsumer3).toHaveBeenCalledWith(videoPipeConsumer); - expect(videoPipeConsumer.id).toBeType('string'); + expect(typeof videoPipeConsumer.id).toBe('string'); expect(videoPipeConsumer.producerId).toBe(videoProducer.id); expect(videoPipeConsumer.closed).toBe(false); expect(videoPipeConsumer.kind).toBe('video'); - expect(videoPipeConsumer.rtpParameters).toBeType('object'); + expect(typeof videoPipeConsumer.rtpParameters).toBe('object'); expect(videoPipeConsumer.rtpParameters.mid).toBeUndefined(); expect(videoPipeConsumer.rtpParameters.codecs.length).toBe(2); expect(videoPipeConsumer.rtpParameters.codecs[0]).toEqual( @@ -535,7 +533,7 @@ test('transport.consume() can be created with user provided mid', async () => test('transport.consume() with incompatible rtpCapabilities rejects with UnsupportedError', async () => { - let invalidDeviceCapabilities; + let invalidDeviceCapabilities: mediasoup.types.RtpCapabilities; invalidDeviceCapabilities = { @@ -592,8 +590,8 @@ test('consumer.dump() succeeds', async () => expect(data.id).toBe(audioConsumer.id); expect(data.producerId).toBe(audioConsumer.producerId); expect(data.kind).toBe(audioConsumer.kind); - expect(data.rtpParameters).toBeType('object'); - expect(data.rtpParameters.codecs).toBeType('array'); + expect(typeof data.rtpParameters).toBe('object'); + expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); expect(data.rtpParameters.codecs.length).toBe(1); expect(data.rtpParameters.codecs[0].mimeType).toBe('audio/opus'); expect(data.rtpParameters.codecs[0].payloadType).toBe(100); @@ -608,7 +606,7 @@ test('consumer.dump() succeeds', async () => bar : '333' }); expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); - expect(data.rtpParameters.headerExtensions).toBeType('array'); + expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); expect(data.rtpParameters.headerExtensions.length).toBe(3); expect(data.rtpParameters.headerExtensions).toEqual( [ @@ -631,21 +629,21 @@ test('consumer.dump() succeeds', async () => encrypt : false } ]); - expect(data.rtpParameters.encodings).toBeType('array'); + expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); expect(data.rtpParameters.encodings.length).toBe(1); expect(data.rtpParameters.encodings).toEqual( [ { codecPayloadType : 100, - ssrc : audioConsumer.rtpParameters.encodings[0].ssrc + ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc } ]); expect(data.type).toBe('simple'); - expect(data.consumableRtpEncodings).toBeType('array'); + expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); expect(data.consumableRtpEncodings.length).toBe(1); expect(data.consumableRtpEncodings).toEqual( [ - { ssrc: audioProducer.consumableRtpParameters.encodings[0].ssrc } + { ssrc: audioProducer.consumableRtpParameters.encodings?.[0].ssrc } ]); expect(data.supportedCodecPayloadTypes).toEqual([ 100 ]); expect(data.paused).toBe(false); @@ -657,8 +655,8 @@ test('consumer.dump() succeeds', async () => expect(data.id).toBe(videoConsumer.id); expect(data.producerId).toBe(videoConsumer.producerId); expect(data.kind).toBe(videoConsumer.kind); - expect(data.rtpParameters).toBeType('object'); - expect(data.rtpParameters.codecs).toBeType('array'); + expect(typeof data.rtpParameters).toBe('object'); + expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); expect(data.rtpParameters.codecs.length).toBe(2); expect(data.rtpParameters.codecs[0].mimeType).toBe('video/H264'); expect(data.rtpParameters.codecs[0].payloadType).toBe(103); @@ -677,7 +675,7 @@ test('consumer.dump() succeeds', async () => { type: 'ccm', parameter: 'fir' }, { type: 'goog-remb' } ]); - expect(data.rtpParameters.headerExtensions).toBeType('array'); + expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); expect(data.rtpParameters.headerExtensions.length).toBe(4); expect(data.rtpParameters.headerExtensions).toEqual( [ @@ -706,28 +704,28 @@ test('consumer.dump() succeeds', async () => encrypt : false } ]); - expect(data.rtpParameters.encodings).toBeType('array'); + expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); expect(data.rtpParameters.encodings.length).toBe(1); expect(data.rtpParameters.encodings).toMatchObject( [ { codecPayloadType : 103, - ssrc : videoConsumer.rtpParameters.encodings[0].ssrc, + ssrc : videoConsumer.rtpParameters.encodings?.[0].ssrc, rtx : { - ssrc : videoConsumer.rtpParameters.encodings[0].rtx.ssrc + ssrc : videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc }, scalabilityMode : 'S4T1' } ]); - expect(data.consumableRtpEncodings).toBeType('array'); + expect(Array.isArray(data.consumableRtpEncodings)).toBe(true); expect(data.consumableRtpEncodings.length).toBe(4); expect(data.consumableRtpEncodings).toEqual( [ - { ssrc: videoProducer.consumableRtpParameters.encodings[0].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings[1].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings[2].ssrc }, - { ssrc: videoProducer.consumableRtpParameters.encodings[3].ssrc } + { ssrc: videoProducer.consumableRtpParameters.encodings?.[0].ssrc }, + { ssrc: videoProducer.consumableRtpParameters.encodings?.[1].ssrc }, + { ssrc: videoProducer.consumableRtpParameters.encodings?.[2].ssrc }, + { ssrc: videoProducer.consumableRtpParameters.encodings?.[3].ssrc } ]); expect(data.supportedCodecPayloadTypes).toEqual([ 103 ]); expect(data.paused).toBe(true); @@ -746,7 +744,7 @@ test('consumer.getStats() succeeds', async () => type : 'outbound-rtp', kind : 'audio', mimeType : 'audio/opus', - ssrc : audioConsumer.rtpParameters.encodings[0].ssrc + ssrc : audioConsumer.rtpParameters.encodings?.[0].ssrc }) ]); @@ -759,7 +757,7 @@ test('consumer.getStats() succeeds', async () => type : 'outbound-rtp', kind : 'video', mimeType : 'video/H264', - ssrc : videoConsumer.rtpParameters.encodings[0].ssrc + ssrc : videoConsumer.rtpParameters.encodings?.[0].ssrc }) ]); }, 2000); @@ -792,19 +790,23 @@ test('consumer.setPreferredLayers() succeed', async () => test('consumer.setPreferredLayers() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(videoConsumer.setPreferredLayers({})) .rejects .toThrow(TypeError); + // @ts-ignore await expect(videoConsumer.setPreferredLayers({ foo: '123' })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(videoConsumer.setPreferredLayers('foo')) .rejects .toThrow(TypeError); // Missing spatialLayer. + // @ts-ignore await expect(videoConsumer.setPreferredLayers({ temporalLayer: 2 })) .rejects .toThrow(TypeError); @@ -818,6 +820,7 @@ test('consumer.setPriority() succeed', async () => test('consumer.setPriority() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(videoConsumer.setPriority()) .rejects .toThrow(TypeError); @@ -826,6 +829,7 @@ test('consumer.setPriority() with wrong arguments rejects with TypeError', async .rejects .toThrow(TypeError); + // @ts-ignore await expect(videoConsumer.setPriority('foo')) .rejects .toThrow(TypeError); @@ -849,6 +853,7 @@ test('consumer.enableTraceEvent() succeed', async () => .resolves .toMatchObject({ traceEventTypes: '' }); + // @ts-ignore await audioConsumer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); await expect(audioConsumer.dump()) .resolves @@ -862,14 +867,17 @@ test('consumer.enableTraceEvent() succeed', async () => test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(audioConsumer.enableTraceEvent(123)) .rejects .toThrow(TypeError); + // @ts-ignore await expect(audioConsumer.enableTraceEvent('rtp')) .rejects .toThrow(TypeError); + // @ts-ignore await expect(audioConsumer.enableTraceEvent([ 'fir', 123.123 ])) .rejects .toThrow(TypeError); @@ -877,7 +885,7 @@ test('consumer.enableTraceEvent() with wrong arguments rejects with TypeError', test('Consumer emits "producerpause" and "producerresume"', async () => { - await new Promise((resolve) => + await new Promise((resolve) => { audioConsumer.on('producerpause', resolve); audioProducer.pause(); @@ -886,7 +894,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => expect(audioConsumer.paused).toBe(false); expect(audioConsumer.producerPaused).toBe(true); - await new Promise((resolve) => + await new Promise((resolve) => { audioConsumer.on('producerresume', resolve); audioProducer.resume(); @@ -961,6 +969,7 @@ test('Consumer methods reject if closed', async () => .rejects .toThrow(Error); + // @ts-ignore await expect(audioConsumer.setPreferredLayers({})) .rejects .toThrow(Error); @@ -986,7 +995,7 @@ test('Consumer emits "producerclose" if Producer is closed', async () => audioConsumer.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { audioConsumer.on('producerclose', resolve); audioProducer.close(); @@ -1008,7 +1017,7 @@ test('Consumer emits "transportclose" if Transport is closed', async () => videoConsumer.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { videoConsumer.on('transportclose', resolve); transport2.close(); diff --git a/node/tests/test-DataConsumer.js b/node/src/tests/test-DataConsumer.ts similarity index 85% rename from node/tests/test-DataConsumer.js rename to node/src/tests/test-DataConsumer.ts index 5e0816de549..08241fcf3e1 100644 --- a/node/tests/test-DataConsumer.js +++ b/node/src/tests/test-DataConsumer.ts @@ -1,19 +1,17 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport1; -let transport2; -let transport3; -let dataProducer; -let dataConsumer1; -let dataConsumer2; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport1: mediasoup.types.WebRtcTransport; +let transport2: mediasoup.types.PlainTransport; +let transport3: mediasoup.types.DirectTransport; +let dataProducer: mediasoup.types.DataProducer; +let dataConsumer1: mediasoup.types.DataConsumer; +let dataConsumer2: mediasoup.types.DataConsumer; -const dataProducerParameters = +const dataProducerParameters: mediasoup.types.DataProducerOptions = { sctpStreamParameters : { @@ -60,15 +58,15 @@ test('transport.consumeData() succeeds', async () => expect(onObserverNewDataConsumer).toHaveBeenCalledTimes(1); expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer1); - expect(dataConsumer1.id).toBeType('string'); + expect(typeof dataConsumer1.id).toBe('string'); expect(dataConsumer1.dataProducerId).toBe(dataProducer.id); expect(dataConsumer1.closed).toBe(false); expect(dataConsumer1.type).toBe('sctp'); - expect(dataConsumer1.sctpStreamParameters).toBeType('object'); - expect(dataConsumer1.sctpStreamParameters.streamId).toBeType('number'); - expect(dataConsumer1.sctpStreamParameters.ordered).toBe(false); - expect(dataConsumer1.sctpStreamParameters.maxPacketLifeTime).toBe(4000); - expect(dataConsumer1.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(typeof dataConsumer1.sctpStreamParameters).toBe('object'); + expect(typeof dataConsumer1.sctpStreamParameters?.streamId).toBe('number'); + expect(dataConsumer1.sctpStreamParameters?.ordered).toBe(false); + expect(dataConsumer1.sctpStreamParameters?.maxPacketLifeTime).toBe(4000); + expect(dataConsumer1.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(dataConsumer1.label).toBe('foo'); expect(dataConsumer1.protocol).toBe('bar'); expect(dataConsumer1.appData).toEqual({ baz: 'LOL' }); @@ -98,9 +96,9 @@ test('dataConsumer.dump() succeeds', async () => expect(data.id).toBe(dataConsumer1.id); expect(data.dataProducerId).toBe(dataConsumer1.dataProducerId); expect(data.type).toBe('sctp'); - expect(data.sctpStreamParameters).toBeType('object'); + expect(typeof data.sctpStreamParameters).toBe('object'); expect(data.sctpStreamParameters.streamId) - .toBe(dataConsumer1.sctpStreamParameters.streamId); + .toBe(dataConsumer1.sctpStreamParameters?.streamId); expect(data.sctpStreamParameters.ordered).toBe(false); expect(data.sctpStreamParameters.maxPacketLifeTime).toBe(4000); expect(data.sctpStreamParameters.maxRetransmits).toBeUndefined(); @@ -138,7 +136,7 @@ test('transport.consumeData() on a DirectTransport succeeds', async () => expect(onObserverNewDataConsumer).toHaveBeenCalledTimes(1); expect(onObserverNewDataConsumer).toHaveBeenCalledWith(dataConsumer2); - expect(dataConsumer2.id).toBeType('string'); + expect(typeof dataConsumer2.id).toBe('string'); expect(dataConsumer2.dataProducerId).toBe(dataProducer.id); expect(dataConsumer2.closed).toBe(false); expect(dataConsumer2.type).toBe('direct'); @@ -235,7 +233,7 @@ test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async ( dataConsumer1.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { dataConsumer1.on('dataproducerclose', resolve); dataProducer.close(); @@ -257,7 +255,7 @@ test('DataConsumer emits "transportclose" if Transport is closed', async () => dataConsumer1.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { dataConsumer1.on('transportclose', resolve); transport2.close(); diff --git a/node/tests/test-DataProducer.js b/node/src/tests/test-DataProducer.ts similarity index 83% rename from node/tests/test-DataProducer.js rename to node/src/tests/test-DataProducer.ts index 866d2206a42..711fde3d790 100644 --- a/node/tests/test-DataProducer.js +++ b/node/src/tests/test-DataProducer.ts @@ -1,15 +1,13 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport1; -let transport2; -let dataProducer1; -let dataProducer2; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport1: mediasoup.types.WebRtcTransport; +let transport2: mediasoup.types.PlainTransport; +let dataProducer1: mediasoup.types.DataProducer; +let dataProducer2: mediasoup.types.DataProducer; beforeAll(async () => { @@ -48,14 +46,14 @@ test('transport1.produceData() succeeds', async () => expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); expect(onObserverNewDataProducer).toHaveBeenCalledWith(dataProducer1); - expect(dataProducer1.id).toBeType('string'); + expect(typeof dataProducer1.id).toBe('string'); expect(dataProducer1.closed).toBe(false); expect(dataProducer1.type).toBe('sctp'); - expect(dataProducer1.sctpStreamParameters).toBeType('object'); - expect(dataProducer1.sctpStreamParameters.streamId).toBe(666); - expect(dataProducer1.sctpStreamParameters.ordered).toBe(true); - expect(dataProducer1.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); - expect(dataProducer1.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(typeof dataProducer1.sctpStreamParameters).toBe('object'); + expect(dataProducer1.sctpStreamParameters?.streamId).toBe(666); + expect(dataProducer1.sctpStreamParameters?.ordered).toBe(true); + expect(dataProducer1.sctpStreamParameters?.maxPacketLifeTime).toBeUndefined(); + expect(dataProducer1.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(dataProducer1.label).toBe('foo'); expect(dataProducer1.protocol).toBe('bar'); expect(dataProducer1.appData).toEqual({ foo: 1, bar: '2' }); @@ -98,14 +96,14 @@ test('transport2.produceData() succeeds', async () => expect(onObserverNewDataProducer).toHaveBeenCalledTimes(1); expect(onObserverNewDataProducer).toHaveBeenCalledWith(dataProducer2); - expect(dataProducer2.id).toBeType('string'); + expect(typeof dataProducer2.id).toBe('string'); expect(dataProducer2.closed).toBe(false); expect(dataProducer2.type).toBe('sctp'); - expect(dataProducer2.sctpStreamParameters).toBeType('object'); - expect(dataProducer2.sctpStreamParameters.streamId).toBe(777); - expect(dataProducer2.sctpStreamParameters.ordered).toBe(false); - expect(dataProducer2.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); - expect(dataProducer2.sctpStreamParameters.maxRetransmits).toBe(3); + expect(typeof dataProducer2.sctpStreamParameters).toBe('object'); + expect(dataProducer2.sctpStreamParameters?.streamId).toBe(777); + expect(dataProducer2.sctpStreamParameters?.ordered).toBe(false); + expect(dataProducer2.sctpStreamParameters?.maxPacketLifeTime).toBeUndefined(); + expect(dataProducer2.sctpStreamParameters?.maxRetransmits).toBe(3); expect(dataProducer2.label).toBe('foo'); expect(dataProducer2.protocol).toBe('bar'); expect(dataProducer2.appData).toEqual({ foo: 1, bar: '2' }); @@ -137,6 +135,7 @@ test('transport1.produceData() with wrong arguments rejects with TypeError', asy // Missing or empty sctpStreamParameters.streamId. await expect(transport1.produceData( { + // @ts-ignore sctpStreamParameters : { foo: 'foo' } })) .rejects @@ -179,7 +178,7 @@ test('dataProducer.dump() succeeds', async () => expect(data.id).toBe(dataProducer1.id); expect(data.type).toBe('sctp'); - expect(data.sctpStreamParameters).toBeType('object'); + expect(typeof data.sctpStreamParameters).toBe('object'); expect(data.sctpStreamParameters.streamId).toBe(666); expect(data.sctpStreamParameters.ordered).toBe(true); expect(data.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); @@ -191,7 +190,7 @@ test('dataProducer.dump() succeeds', async () => expect(data.id).toBe(dataProducer2.id); expect(data.type).toBe('sctp'); - expect(data.sctpStreamParameters).toBeType('object'); + expect(typeof data.sctpStreamParameters).toBe('object'); expect(data.sctpStreamParameters.streamId).toBe(777); expect(data.sctpStreamParameters.ordered).toBe(false); expect(data.sctpStreamParameters.maxPacketLifeTime).toBeUndefined(); @@ -274,7 +273,7 @@ test('DataProducer emits "transportclose" if Transport is closed', async () => dataProducer2.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { dataProducer2.on('transportclose', resolve); transport2.close(); diff --git a/node/tests/test-DirectTransport.js b/node/src/tests/test-DirectTransport.ts similarity index 91% rename from node/tests/test-DirectTransport.js rename to node/src/tests/test-DirectTransport.ts index f631d0f6a69..a00e88840d3 100644 --- a/node/tests/test-DirectTransport.js +++ b/node/src/tests/test-DirectTransport.ts @@ -1,12 +1,10 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport: mediasoup.types.DirectTransport; beforeAll(async () => { @@ -42,7 +40,7 @@ test('router.createDirectTransport() succeeds', async () => expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(transport1); - expect(transport1.id).toBeType('string'); + expect(typeof transport1.id).toBe('string'); expect(transport1.closed).toBe(false); expect(transport1.appData).toEqual({ foo: 'bar' }); @@ -54,19 +52,16 @@ test('router.createDirectTransport() succeeds', async () => expect(data1.consumerIds).toEqual([]); expect(data1.dataProducerIds).toEqual([]); expect(data1.dataConsumerIds).toEqual([]); - expect(data1.recvRtpHeaderExtensions).toBeType('object'); - expect(data1.rtpListener).toBeType('object'); + expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(typeof data1.rtpListener).toBe('object'); transport1.close(); expect(transport1.closed).toBe(true); - - await expect(router.createDirectTransport()) - .resolves - .toBeType('object'); }, 2000); test('router.createDirectTransport() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(router.createDirectTransport({ maxMessageSize: 'foo' })) .rejects .toThrow(TypeError); @@ -80,11 +75,11 @@ test('directTransport.getStats() succeeds', async () => { const data = await transport.getStats(); - expect(data).toBeType('array'); + expect(Array.isArray(data)).toBe(true); expect(data.length).toBe(1); expect(data[0].type).toBe('direct-transport'); expect(data[0].transportId).toBe(transport.id); - expect(data[0].timestamp).toBeType('number'); + expect(typeof data[0].timestamp).toBe('number'); expect(data[0].bytesReceived).toBe(0); expect(data[0].recvBitrate).toBe(0); expect(data[0].bytesSent).toBe(0); @@ -127,7 +122,7 @@ test('dataProducer.send() succeeds', async () => let lastSentMessageId = 0; let lastRecvMessageId = 0; - await new Promise((resolve) => + await new Promise((resolve) => { // Send messages over the sctpSendStream created above. const interval = setInterval(() => @@ -235,7 +230,7 @@ test('DirectTransport emits "routerclose" if Router is closed', async () => transport2.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { transport2.on('routerclose', resolve); router2.close(); @@ -251,7 +246,7 @@ test('DirectTransport emits "routerclose" if Worker is closed', async () => transport.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { transport.on('routerclose', resolve); worker.close(); diff --git a/node/tests/test-PipeTransport.js b/node/src/tests/test-PipeTransport.ts similarity index 85% rename from node/tests/test-PipeTransport.js rename to node/src/tests/test-PipeTransport.ts index cef4c90e150..6ececbbe5e1 100644 --- a/node/tests/test-PipeTransport.js +++ b/node/src/tests/test-PipeTransport.ts @@ -1,23 +1,22 @@ -const { toBeType } = require('jest-tobetype'); -const pickPort = require('pick-port'); -const mediasoup = require('../lib/'); +// @ts-ignore +import * as pickPort from 'pick-port'; +import * as mediasoup from '../'; + const { createWorker } = mediasoup; -expect.extend({ toBeType }); - -let worker1; -let worker2; -let router1; -let router2; -let transport1; -let audioProducer; -let videoProducer; -let transport2; -let videoConsumer; -let dataProducer; -let dataConsumer; - -const mediaCodecs = +let worker1: mediasoup.types.Worker; +let worker2: mediasoup.types.Worker; +let router1: mediasoup.types.Router; +let router2: mediasoup.types.Router; +let transport1: mediasoup.types.WebRtcTransport; +let audioProducer: mediasoup.types.Producer; +let videoProducer: mediasoup.types.Producer; +let transport2: mediasoup.types.WebRtcTransport; +let videoConsumer: mediasoup.types.Consumer; +let dataProducer: mediasoup.types.DataProducer; +let dataConsumer: mediasoup.types.DataConsumer; + +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -32,7 +31,7 @@ const mediaCodecs = } ]; -const audioProducerParameters = +const audioProducerParameters: mediasoup.types.ProducerOptions = { kind : 'audio', rtpParameters : @@ -68,7 +67,7 @@ const audioProducerParameters = appData : { foo: 'bar1' } }; -const videoProducerParameters = +const videoProducerParameters: mediasoup.types.ProducerOptions = { kind : 'video', rtpParameters : @@ -118,7 +117,7 @@ const videoProducerParameters = appData : { foo: 'bar2' } }; -const dataProducerParameters = +const dataProducerParameters: mediasoup.types.DataProducerOptions = { sctpStreamParameters : { @@ -130,7 +129,7 @@ const dataProducerParameters = protocol : 'bar' }; -const consumerDeviceCapabilities = +const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { codecs : [ @@ -227,7 +226,10 @@ test('router.pipeToRouter() succeeds with audio', async () => { producerId : audioProducer.id, router : router2 - }); + }) as { + pipeConsumer: mediasoup.types.Consumer; + pipeProducer: mediasoup.types.Producer; + }; dump = await router1.dump(); @@ -243,10 +245,10 @@ test('router.pipeToRouter() succeeds with audio', async () => // - PipeTransport between router2 and router1. expect(dump.transportIds.length).toBe(2); - expect(pipeConsumer.id).toBeType('string'); + expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); expect(pipeConsumer.kind).toBe('audio'); - expect(pipeConsumer.rtpParameters).toBeType('object'); + expect(typeof pipeConsumer.rtpParameters).toBe('object'); expect(pipeConsumer.rtpParameters.mid).toBeUndefined(); expect(pipeConsumer.rtpParameters.codecs).toEqual( [ @@ -289,7 +291,7 @@ test('router.pipeToRouter() succeeds with audio', async () => expect(pipeProducer.id).toBe(audioProducer.id); expect(pipeProducer.closed).toBe(false); expect(pipeProducer.kind).toBe('audio'); - expect(pipeProducer.rtpParameters).toBeType('object'); + expect(typeof pipeProducer.rtpParameters).toBe('object'); expect(pipeProducer.rtpParameters.mid).toBeUndefined(); expect(pipeProducer.rtpParameters.codecs).toEqual( [ @@ -332,7 +334,10 @@ test('router.pipeToRouter() succeeds with video', async () => { producerId : videoProducer.id, router : router2 - }); + }) as { + pipeConsumer: mediasoup.types.Consumer; + pipeProducer: mediasoup.types.Producer; + }; dump = await router1.dump(); @@ -344,10 +349,10 @@ test('router.pipeToRouter() succeeds with video', async () => // No new PipeTransport should has been created. The existing one is used. expect(dump.transportIds.length).toBe(2); - expect(pipeConsumer.id).toBeType('string'); + expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); expect(pipeConsumer.kind).toBe('video'); - expect(pipeConsumer.rtpParameters).toBeType('object'); + expect(typeof pipeConsumer.rtpParameters).toBe('object'); expect(pipeConsumer.rtpParameters.mid).toBeUndefined(); expect(pipeConsumer.rtpParameters.codecs).toEqual( [ @@ -408,7 +413,7 @@ test('router.pipeToRouter() succeeds with video', async () => expect(pipeProducer.id).toBe(videoProducer.id); expect(pipeProducer.closed).toBe(false); expect(pipeProducer.kind).toBe('video'); - expect(pipeProducer.rtpParameters).toBeType('object'); + expect(typeof pipeProducer.rtpParameters).toBe('object'); expect(pipeProducer.rtpParameters.mid).toBeUndefined(); expect(pipeProducer.rtpParameters.codecs).toEqual( [ @@ -487,10 +492,10 @@ test('router.createPipeTransport() with enableRtx succeeds', async () => const pipeConsumer = await pipeTransport.consume({ producerId: videoProducer.id }); - expect(pipeConsumer.id).toBeType('string'); + expect(typeof pipeConsumer.id).toBe('string'); expect(pipeConsumer.closed).toBe(false); expect(pipeConsumer.kind).toBe('video'); - expect(pipeConsumer.rtpParameters).toBeType('object'); + expect(typeof pipeConsumer.rtpParameters).toBe('object'); expect(pipeConsumer.rtpParameters.mid).toBeUndefined(); expect(pipeConsumer.rtpParameters.codecs).toEqual( [ @@ -588,6 +593,7 @@ test('router.createPipeTransport() with invalid srtpParameters must fail', async { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : 'invalid' })) .rejects @@ -604,10 +610,10 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => enableSrtp : true }); - expect(pipeTransport.id).toBeType('string'); - expect(pipeTransport.srtpParameters).toBeType('object'); + expect(typeof pipeTransport.id).toBe('string'); + expect(typeof pipeTransport.srtpParameters).toBe('object'); // The master length of AEAD_AES_256_GCM. - expect(pipeTransport.srtpParameters.keyBase64.length).toBe(60); + expect(pipeTransport.srtpParameters?.keyBase64.length).toBe(60); // Missing srtpParameters. await expect(pipeTransport.connect( @@ -623,6 +629,7 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : 1 })) .rejects @@ -633,6 +640,7 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : { keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' @@ -646,6 +654,7 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : { cryptoSuite : 'AEAD_AES_256_GCM' @@ -661,6 +670,7 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => port : 9999, srtpParameters : { + // @ts-ignore cryptoSuite : 'FOO', keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' } @@ -675,6 +685,7 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => port : 9999, srtpParameters : { + // @ts-ignore cryptoSuite : 123, keyBase64 : 'YTdjcDBvY2JoMGY5YXNlNDc0eDJsdGgwaWRvNnJsamRrdG16aWVpZHphdHo=' } @@ -690,6 +701,7 @@ test('router.createPipeTransport() with enableSrtp succeeds', async () => srtpParameters : { cryptoSuite : 'AEAD_AES_256_GCM', + // @ts-ignore keyBase64 : [] } })) @@ -735,10 +747,10 @@ test('transport.consume() for a pipe Producer succeeds', async () => rtpCapabilities : consumerDeviceCapabilities }); - expect(videoConsumer.id).toBeType('string'); + expect(typeof videoConsumer.id).toBe('string'); expect(videoConsumer.closed).toBe(false); expect(videoConsumer.kind).toBe('video'); - expect(videoConsumer.rtpParameters).toBeType('object'); + expect(typeof videoConsumer.rtpParameters).toBe('object'); expect(videoConsumer.rtpParameters.mid).toBe('0'); expect(videoConsumer.rtpParameters.codecs).toEqual( [ @@ -780,10 +792,10 @@ test('transport.consume() for a pipe Producer succeeds', async () => parameters : {} } ]); - expect(videoConsumer.rtpParameters.encodings.length).toBe(1); - expect(videoConsumer.rtpParameters.encodings[0].ssrc).toBeType('number'); - expect(videoConsumer.rtpParameters.encodings[0].rtx).toBeType('object'); - expect(videoConsumer.rtpParameters.encodings[0].rtx.ssrc).toBeType('number'); + expect(videoConsumer.rtpParameters.encodings?.length).toBe(1); + expect(typeof videoConsumer.rtpParameters.encodings?.[0].ssrc).toBe('number'); + expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx).toBe('object'); + expect(typeof videoConsumer.rtpParameters.encodings?.[0].rtx?.ssrc).toBe('number'); expect(videoConsumer.type).toBe('simulcast'); expect(videoConsumer.paused).toBe(false); expect(videoConsumer.producerPaused).toBe(true); @@ -802,7 +814,7 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.producerPaused).toBe(true); expect(videoConsumer.paused).toBe(false); - promise = new Promise((resolve) => videoConsumer.once('producerresume', resolve)); + promise = new Promise((resolve) => videoConsumer.once('producerresume', resolve)); await videoProducer.resume(); await promise; @@ -810,7 +822,7 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.paused).toBe(false); - promise = new Promise((resolve) => videoConsumer.once('producerpause', resolve)); + promise = new Promise((resolve) => videoConsumer.once('producerpause', resolve)); await videoProducer.pause(); await promise; @@ -826,7 +838,7 @@ test('producer.close() is transmitted to pipe Consumer', async () => expect(videoProducer.closed).toBe(true); if (!videoConsumer.closed) - await new Promise((resolve) => videoConsumer.once('producerclose', resolve)); + await new Promise((resolve) => videoConsumer.once('producerclose', resolve)); expect(videoConsumer.closed).toBe(true); }, 2000); @@ -839,7 +851,10 @@ test('router.pipeToRouter() succeeds with data', async () => { dataProducerId : dataProducer.id, router : router2 - }); + }) as { + pipeDataConsumer: mediasoup.types.DataConsumer; + pipeDataProducer: mediasoup.types.DataProducer; + }; dump = await router1.dump(); @@ -855,25 +870,25 @@ test('router.pipeToRouter() succeeds with data', async () => // - PipeTransport between router2 and router1. expect(dump.transportIds.length).toBe(2); - expect(pipeDataConsumer.id).toBeType('string'); + expect(typeof pipeDataConsumer.id).toBe('string'); expect(pipeDataConsumer.closed).toBe(false); expect(pipeDataConsumer.type).toBe('sctp'); - expect(pipeDataConsumer.sctpStreamParameters).toBeType('object'); - expect(pipeDataConsumer.sctpStreamParameters.streamId).toBeType('number'); - expect(pipeDataConsumer.sctpStreamParameters.ordered).toBe(false); - expect(pipeDataConsumer.sctpStreamParameters.maxPacketLifeTime).toBe(5000); - expect(pipeDataConsumer.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(typeof pipeDataConsumer.sctpStreamParameters).toBe('object'); + expect(typeof pipeDataConsumer.sctpStreamParameters?.streamId).toBe('number'); + expect(pipeDataConsumer.sctpStreamParameters?.ordered).toBe(false); + expect(pipeDataConsumer.sctpStreamParameters?.maxPacketLifeTime).toBe(5000); + expect(pipeDataConsumer.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(pipeDataConsumer.label).toBe('foo'); expect(pipeDataConsumer.protocol).toBe('bar'); expect(pipeDataProducer.id).toBe(dataProducer.id); expect(pipeDataProducer.closed).toBe(false); expect(pipeDataProducer.type).toBe('sctp'); - expect(pipeDataProducer.sctpStreamParameters).toBeType('object'); - expect(pipeDataProducer.sctpStreamParameters.streamId).toBeType('number'); - expect(pipeDataProducer.sctpStreamParameters.ordered).toBe(false); - expect(pipeDataProducer.sctpStreamParameters.maxPacketLifeTime).toBe(5000); - expect(pipeDataProducer.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(typeof pipeDataProducer.sctpStreamParameters).toBe('object'); + expect(typeof pipeDataProducer.sctpStreamParameters?.streamId).toBe('number'); + expect(pipeDataProducer.sctpStreamParameters?.ordered).toBe(false); + expect(pipeDataProducer.sctpStreamParameters?.maxPacketLifeTime).toBe(5000); + expect(pipeDataProducer.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(pipeDataProducer.label).toBe('foo'); expect(pipeDataProducer.protocol).toBe('bar'); }, 2000); @@ -885,14 +900,14 @@ test('transport.dataConsume() for a pipe DataProducer succeeds', async () => dataProducerId : dataProducer.id }); - expect(dataConsumer.id).toBeType('string'); + expect(typeof dataConsumer.id).toBe('string'); expect(dataConsumer.closed).toBe(false); expect(dataConsumer.type).toBe('sctp'); - expect(dataConsumer.sctpStreamParameters).toBeType('object'); - expect(dataConsumer.sctpStreamParameters.streamId).toBeType('number'); - expect(dataConsumer.sctpStreamParameters.ordered).toBe(false); - expect(dataConsumer.sctpStreamParameters.maxPacketLifeTime).toBe(5000); - expect(dataConsumer.sctpStreamParameters.maxRetransmits).toBeUndefined(); + expect(typeof dataConsumer.sctpStreamParameters).toBe('object'); + expect(typeof dataConsumer.sctpStreamParameters?.streamId).toBe('number'); + expect(dataConsumer.sctpStreamParameters?.ordered).toBe(false); + expect(dataConsumer.sctpStreamParameters?.maxPacketLifeTime).toBe(5000); + expect(dataConsumer.sctpStreamParameters?.maxRetransmits).toBeUndefined(); expect(dataConsumer.label).toBe('foo'); expect(dataConsumer.protocol).toBe('bar'); }, 2000); @@ -904,7 +919,7 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => expect(dataProducer.closed).toBe(true); if (!dataConsumer.closed) - await new Promise((resolve) => dataConsumer.once('dataproducerclose', resolve)); + await new Promise((resolve) => dataConsumer.once('dataproducerclose', resolve)); expect(dataConsumer.closed).toBe(true); }, 2000); diff --git a/node/tests/test-PlainTransport.js b/node/src/tests/test-PlainTransport.ts similarity index 83% rename from node/tests/test-PlainTransport.js rename to node/src/tests/test-PlainTransport.ts index 34eb75e63cf..bfa2553d9e9 100644 --- a/node/tests/test-PlainTransport.js +++ b/node/src/tests/test-PlainTransport.ts @@ -1,15 +1,14 @@ -const { toBeType } = require('jest-tobetype'); -const pickPort = require('pick-port'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +// @ts-ignore +import * as pickPort from 'pick-port'; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport: mediasoup.types.PlainTransport; -const mediaCodecs = +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -82,12 +81,12 @@ test('router.createPlainTransport() succeeds', async () => expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(transport1); - expect(transport1.id).toBeType('string'); + expect(typeof transport1.id).toBe('string'); expect(transport1.closed).toBe(false); expect(transport1.appData).toEqual({ foo: 'bar' }); - expect(transport1.tuple).toBeType('object'); + expect(typeof transport1.tuple).toBe('object'); expect(transport1.tuple.localIp).toBe('9.9.9.1'); - expect(transport1.tuple.localPort).toBeType('number'); + expect(typeof transport1.tuple.localPort).toBe('number'); expect(transport1.tuple.protocol).toBe('udp'); expect(transport1.rtcpTuple).toBeUndefined(); expect(transport1.sctpParameters).toMatchObject( @@ -110,15 +109,15 @@ test('router.createPlainTransport() succeeds', async () => expect(data1.rtcpTuple).toEqual(transport1.rtcpTuple); expect(data1.sctpParameters).toEqual(transport1.sctpParameters); expect(data1.sctpState).toBe('new'); - expect(data1.recvRtpHeaderExtensions).toBeType('object'); - expect(data1.rtpListener).toBeType('object'); + expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(typeof data1.rtpListener).toBe('object'); transport1.close(); expect(transport1.closed).toBe(true); - await expect(router.createPlainTransport({ listenIp: '127.0.0.1' })) - .resolves - .toBeType('object'); + const anotherTransport = await router.createPlainTransport({ listenIp: '127.0.0.1' }); + + expect(typeof anotherTransport).toBe('object'); const transport2 = await router.createPlainTransport( { @@ -126,17 +125,17 @@ test('router.createPlainTransport() succeeds', async () => rtcpMux : false }); - expect(transport2.id).toBeType('string'); + expect(typeof transport2.id).toBe('string'); expect(transport2.closed).toBe(false); expect(transport2.appData).toEqual({}); - expect(transport2.tuple).toBeType('object'); + expect(typeof transport2.tuple).toBe('object'); expect(transport2.tuple.localIp).toBe('127.0.0.1'); - expect(transport2.tuple.localPort).toBeType('number'); + expect(typeof transport2.tuple.localPort).toBe('number'); expect(transport2.tuple.protocol).toBe('udp'); - expect(transport2.rtcpTuple).toBeType('object'); - expect(transport2.rtcpTuple.localIp).toBe('127.0.0.1'); - expect(transport2.rtcpTuple.localPort).toBeType('number'); - expect(transport2.rtcpTuple.protocol).toBe('udp'); + expect(typeof transport2.rtcpTuple).toBe('object'); + expect(transport2.rtcpTuple?.localIp).toBe('127.0.0.1'); + expect(typeof transport2.rtcpTuple?.localPort).toBe('number'); + expect(transport2.rtcpTuple?.protocol).toBe('udp'); expect(transport2.sctpParameters).toBeUndefined(); expect(transport2.sctpState).toBeUndefined(); @@ -151,6 +150,7 @@ test('router.createPlainTransport() succeeds', async () => test('router.createPlainTransport() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(router.createPlainTransport({})) .rejects .toThrow(TypeError); @@ -159,6 +159,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createPlainTransport({ listenIp: [ '127.0.0.1' ] })) .rejects .toThrow(TypeError); @@ -166,6 +167,7 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' await expect(router.createPlainTransport( { listenIp : '127.0.0.1', + // @ts-ignore appData : 'NOT-AN-OBJECT' })) .rejects @@ -181,10 +183,10 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => enableSrtp : true }); - expect(transport1.id).toBeType('string'); - expect(transport1.srtpParameters).toBeType('object'); - expect(transport1.srtpParameters.cryptoSuite).toBe('AES_CM_128_HMAC_SHA1_80'); - expect(transport1.srtpParameters.keyBase64.length).toBe(40); + expect(typeof transport1.id).toBe('string'); + expect(typeof transport1.srtpParameters).toBe('object'); + expect(transport1.srtpParameters?.cryptoSuite).toBe('AES_CM_128_HMAC_SHA1_80'); + expect(transport1.srtpParameters?.keyBase64.length).toBe(40); // Missing srtpParameters. await expect(transport1.connect( @@ -200,6 +202,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : 1 })) .rejects @@ -210,6 +213,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : { keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' @@ -223,6 +227,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => { ip : '127.0.0.2', port : 9999, + // @ts-ignore srtpParameters : { cryptoSuite : 'AES_CM_128_HMAC_SHA1_80' @@ -238,6 +243,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => port : 9999, srtpParameters : { + // @ts-ignore cryptoSuite : 'FOO', keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' } @@ -252,6 +258,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => port : 9999, srtpParameters : { + // @ts-ignore cryptoSuite : 123, keyBase64 : 'ZnQ3eWJraDg0d3ZoYzM5cXN1Y2pnaHU5NWxrZTVv' } @@ -267,6 +274,7 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => srtpParameters : { cryptoSuite : 'AES_CM_128_HMAC_SHA1_80', + // @ts-ignore keyBase64 : [] } })) @@ -287,8 +295,8 @@ test('router.createPlainTransport() with enableSrtp succeeds', async () => .resolves .toBeUndefined(); - expect(transport1.srtpParameters.cryptoSuite).toBe('AEAD_AES_256_GCM'); - expect(transport1.srtpParameters.keyBase64.length).toBe(60); + expect(transport1.srtpParameters?.cryptoSuite).toBe('AEAD_AES_256_GCM'); + expect(transport1.srtpParameters?.keyBase64.length).toBe(60); transport1.close(); }, 2000); @@ -304,11 +312,11 @@ test('plainTransport.getStats() succeeds', async () => { const data = await transport.getStats(); - expect(data).toBeType('array'); + expect(Array.isArray(data)).toBe(true); expect(data.length).toBe(1); expect(data[0].type).toBe('plain-rtp-transport'); expect(data[0].transportId).toBe(transport.id); - expect(data[0].timestamp).toBeType('number'); + expect(typeof data[0].timestamp).toBe('number'); expect(data[0].bytesReceived).toBe(0); expect(data[0].recvBitrate).toBe(0); expect(data[0].bytesSent).toBe(0); @@ -323,9 +331,9 @@ test('plainTransport.getStats() succeeds', async () => expect(data[0].rtxSendBitrate).toBe(0); expect(data[0].probationBytesSent).toBe(0); expect(data[0].probationSendBitrate).toBe(0); - expect(data[0].tuple).toBeType('object'); + expect(typeof data[0].tuple).toBe('object'); expect(data[0].tuple.localIp).toBe('4.4.4.4'); - expect(data[0].tuple.localPort).toBeType('number'); + expect(typeof data[0].tuple.localPort).toBe('number'); expect(data[0].tuple.protocol).toBe('udp'); expect(data[0].rtcpTuple).toBeUndefined(); }, 2000); @@ -344,9 +352,9 @@ test('plainTransport.connect() succeeds', async () => expect(transport.tuple.remoteIp).toBe('1.2.3.4'); expect(transport.tuple.remotePort).toBe(1234); expect(transport.tuple.protocol).toBe('udp'); - expect(transport.rtcpTuple.remoteIp).toBe('1.2.3.4'); - expect(transport.rtcpTuple.remotePort).toBe(1235); - expect(transport.rtcpTuple.protocol).toBe('udp'); + expect(transport.rtcpTuple?.remoteIp).toBe('1.2.3.4'); + expect(transport.rtcpTuple?.remotePort).toBe(1235); + expect(transport.rtcpTuple?.protocol).toBe('udp'); }, 2000); test('plainTransport.connect() with wrong arguments rejects with TypeError', async () => @@ -374,10 +382,12 @@ test('plainTransport.connect() with wrong arguments rejects with TypeError', asy .rejects .toThrow(TypeError); + // @ts-ignore await expect(transport.connect({ ip: '127.0.0.1', port: 1234, __rtcpPort: 1235 })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(transport.connect({ ip: '127.0.0.1', __port: 'chicken', rtcpPort: 1235 })) .rejects .toThrow(TypeError); @@ -430,7 +440,7 @@ test('PlainTransport emits "routerclose" if Router is closed', async () => transport2.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { transport2.on('routerclose', resolve); router2.close(); @@ -446,7 +456,7 @@ test('PlainTransport emits "routerclose" if Worker is closed', async () => transport.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { transport.on('routerclose', resolve); worker.close(); diff --git a/node/tests/test-Producer.js b/node/src/tests/test-Producer.ts similarity index 91% rename from node/tests/test-Producer.js rename to node/src/tests/test-Producer.ts index 8425866e367..3c86e6680c7 100644 --- a/node/tests/test-Producer.js +++ b/node/src/tests/test-Producer.ts @@ -1,18 +1,16 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; -const { UnsupportedError } = require('../lib/errors'); +import * as mediasoup from '../'; +import { UnsupportedError } from '../errors'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport1; -let transport2; -let audioProducer; -let videoProducer; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport1: mediasoup.types.WebRtcTransport; +let transport2: mediasoup.types.PlainTransport; +let audioProducer: mediasoup.types.Producer; +let videoProducer: mediasoup.types.Producer; -const mediaCodecs = +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -110,13 +108,13 @@ test('transport1.produce() succeeds', async () => expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(audioProducer); - expect(audioProducer.id).toBeType('string'); + expect(typeof audioProducer.id).toBe('string'); expect(audioProducer.closed).toBe(false); expect(audioProducer.kind).toBe('audio'); - expect(audioProducer.rtpParameters).toBeType('object'); + expect(typeof audioProducer.rtpParameters).toBe('object'); expect(audioProducer.type).toBe('simple'); // Private API. - expect(audioProducer.consumableRtpParameters).toBeType('object'); + expect(typeof audioProducer.consumableRtpParameters).toBe('object'); expect(audioProducer.paused).toBe(false); expect(audioProducer.score).toEqual([]); expect(audioProducer.appData).toEqual({ foo: 1, bar: '2' }); @@ -204,13 +202,13 @@ test('transport2.produce() succeeds', async () => expect(onObserverNewProducer).toHaveBeenCalledTimes(1); expect(onObserverNewProducer).toHaveBeenCalledWith(videoProducer); - expect(videoProducer.id).toBeType('string'); + expect(typeof videoProducer.id).toBe('string'); expect(videoProducer.closed).toBe(false); expect(videoProducer.kind).toBe('video'); - expect(videoProducer.rtpParameters).toBeType('object'); + expect(typeof videoProducer.rtpParameters).toBe('object'); expect(videoProducer.type).toBe('simulcast'); // Private API. - expect(videoProducer.consumableRtpParameters).toBeType('object'); + expect(typeof videoProducer.consumableRtpParameters).toBe('object'); expect(videoProducer.paused).toBe(false); expect(videoProducer.score).toEqual([]); expect(videoProducer.appData).toEqual({ foo: 1, bar: '2' }); @@ -237,7 +235,9 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( { await expect(transport1.produce( { + // @ts-ignore kind : 'chicken', + // @ts-ignore rtpParameters : {} })) .rejects @@ -246,12 +246,13 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( await expect(transport1.produce( { kind : 'audio', + // @ts-ignore rtpParameters : {} })) .rejects .toThrow(TypeError); - // Missing or empty rtpParameters.codecs. + // Invalid ssrc. await expect(transport1.produce( { kind : 'audio', @@ -259,6 +260,7 @@ test('transport1.produce() with wrong arguments rejects with TypeError', async ( { codecs : [], headerExtensions : [], + // @ts-ignore encodings : [ { ssrc: '1111' } ], rtcp : { cname: 'qwerty' } } @@ -501,8 +503,8 @@ test('producer.dump() succeeds', async () => expect(data.id).toBe(audioProducer.id); expect(data.kind).toBe(audioProducer.kind); - expect(data.rtpParameters).toBeType('object'); - expect(data.rtpParameters.codecs).toBeType('array'); + expect(typeof data.rtpParameters).toBe('object'); + expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); expect(data.rtpParameters.codecs.length).toBe(1); expect(data.rtpParameters.codecs[0].mimeType).toBe('audio/opus'); expect(data.rtpParameters.codecs[0].payloadType).toBe(0); @@ -517,7 +519,7 @@ test('producer.dump() succeeds', async () => bar : '333' }); expect(data.rtpParameters.codecs[0].rtcpFeedback).toEqual([]); - expect(data.rtpParameters.headerExtensions).toBeType('array'); + expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); expect(data.rtpParameters.headerExtensions.length).toBe(2); expect(data.rtpParameters.headerExtensions).toEqual( [ @@ -534,7 +536,7 @@ test('producer.dump() succeeds', async () => encrypt : false } ]); - expect(data.rtpParameters.encodings).toBeType('array'); + expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); expect(data.rtpParameters.encodings.length).toBe(1); expect(data.rtpParameters.encodings).toEqual( [ @@ -546,8 +548,8 @@ test('producer.dump() succeeds', async () => expect(data.id).toBe(videoProducer.id); expect(data.kind).toBe(videoProducer.kind); - expect(data.rtpParameters).toBeType('object'); - expect(data.rtpParameters.codecs).toBeType('array'); + expect(typeof data.rtpParameters).toBe('object'); + expect(Array.isArray(data.rtpParameters.codecs)).toBe(true); expect(data.rtpParameters.codecs.length).toBe(2); expect(data.rtpParameters.codecs[0].mimeType).toBe('video/H264'); expect(data.rtpParameters.codecs[0].payloadType).toBe(112); @@ -572,7 +574,7 @@ test('producer.dump() succeeds', async () => expect(data.rtpParameters.codecs[1].channels).toBeUndefined(); expect(data.rtpParameters.codecs[1].parameters).toEqual({ apt: 112 }); expect(data.rtpParameters.codecs[1].rtcpFeedback).toEqual([]); - expect(data.rtpParameters.headerExtensions).toBeType('array'); + expect(Array.isArray(data.rtpParameters.headerExtensions)).toBe(true); expect(data.rtpParameters.headerExtensions.length).toBe(2); expect(data.rtpParameters.headerExtensions).toEqual( [ @@ -589,7 +591,7 @@ test('producer.dump() succeeds', async () => encrypt : false } ]); - expect(data.rtpParameters.encodings).toBeType('array'); + expect(Array.isArray(data.rtpParameters.encodings)).toBe(true); expect(data.rtpParameters.encodings.length).toBe(4); expect(data.rtpParameters.encodings).toMatchObject( [ @@ -646,6 +648,7 @@ test('producer.enableTraceEvent() succeed', async () => .resolves .toMatchObject({ traceEventTypes: '' }); + // @ts-ignore await audioProducer.enableTraceEvent([ 'nack', 'FOO', 'fir' ]); await expect(audioProducer.dump()) .resolves @@ -659,14 +662,17 @@ test('producer.enableTraceEvent() succeed', async () => test('producer.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(audioProducer.enableTraceEvent(123)) .rejects .toThrow(TypeError); + // @ts-ignore await expect(audioProducer.enableTraceEvent('rtp')) .rejects .toThrow(TypeError); + // @ts-ignore await expect(audioProducer.enableTraceEvent([ 'fir', 123.123 ])) .rejects .toThrow(TypeError); @@ -741,7 +747,7 @@ test('Producer emits "transportclose" if Transport is closed', async () => videoProducer.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { videoProducer.on('transportclose', resolve); transport2.close(); diff --git a/node/tests/test-Router.js b/node/src/tests/test-Router.ts similarity index 87% rename from node/tests/test-Router.js rename to node/src/tests/test-Router.ts index 6afa36b15ac..c9316ee1f41 100644 --- a/node/tests/test-Router.js +++ b/node/src/tests/test-Router.ts @@ -1,16 +1,14 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; -const { InvalidStateError } = require('../lib/errors'); +import * as mediasoup from '../'; +import { InvalidStateError } from '../errors'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; +let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); afterEach(() => worker && !worker.closed && worker.close()); -const mediaCodecs = +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -54,11 +52,11 @@ test('worker.createRouter() succeeds', async () => expect(onObserverNewRouter).toHaveBeenCalledTimes(1); expect(onObserverNewRouter).toHaveBeenCalledWith(router); - expect(router.id).toBeType('string'); + expect(typeof router.id).toBe('string'); expect(router.closed).toBe(false); - expect(router.rtpCapabilities).toBeType('object'); - expect(router.rtpCapabilities.codecs).toBeType('array'); - expect(router.rtpCapabilities.headerExtensions).toBeType('array'); + expect(typeof router.rtpCapabilities).toBe('object'); + expect(Array.isArray(router.rtpCapabilities.codecs)).toBe(true); + expect(Array.isArray(router.rtpCapabilities.headerExtensions)).toBe(true); expect(router.appData).toEqual({ foo: 123 }); await expect(worker.dump()) @@ -105,10 +103,12 @@ test('worker.createRouter() with wrong arguments rejects with TypeError', async { worker = await createWorker(); + // @ts-ignore await expect(worker.createRouter({ mediaCodecs: {} })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(worker.createRouter({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); @@ -150,7 +150,7 @@ test('Router emits "workerclose" if Worker is closed', async () => router.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { router.on('workerclose', resolve); worker.close(); diff --git a/node/tests/test-WebRtcServer.js b/node/src/tests/test-WebRtcServer.ts similarity index 96% rename from node/tests/test-WebRtcServer.js rename to node/src/tests/test-WebRtcServer.ts index ee84e5c0086..febdea95bfd 100644 --- a/node/tests/test-WebRtcServer.js +++ b/node/src/tests/test-WebRtcServer.ts @@ -1,12 +1,11 @@ -const { toBeType } = require('jest-tobetype'); -const pickPort = require('pick-port'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; -const { InvalidStateError } = require('../lib/errors'); +// @ts-ignore +import * as pickPort from 'pick-port'; +import * as mediasoup from '../'; +import { InvalidStateError } from '../errors'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; +let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); afterEach(() => worker && !worker.closed && worker.close()); @@ -43,7 +42,7 @@ test('worker.createWebRtcServer() succeeds', async () => expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); - expect(webRtcServer.id).toBeType('string'); + expect(typeof webRtcServer.id).toBe('string'); expect(webRtcServer.closed).toBe(false); expect(webRtcServer.appData).toEqual({ foo: 123 }); @@ -118,7 +117,7 @@ test('worker.createWebRtcServer() without specifying port succeeds', async () => expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); - expect(webRtcServer.id).toBeType('string'); + expect(typeof webRtcServer.id).toBe('string'); expect(webRtcServer.closed).toBe(false); expect(webRtcServer.appData).toEqual({ foo: 123 }); @@ -170,14 +169,17 @@ test('worker.createWebRtcServer() with wrong arguments rejects with TypeError', { worker = await createWorker(); - await expect(worker.createWebRtcServer({ })) + // @ts-ignore + await expect(worker.createWebRtcServer({})) .rejects .toThrow(TypeError); + // @ts-ignore await expect(worker.createWebRtcServer({ listenInfos: 'NOT-AN-ARRAY' })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(worker.createWebRtcServer({ listenInfos: [ 'NOT-AN-OBJECT' ] })) .rejects .toThrow(TypeError); @@ -316,7 +318,7 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => webRtcServer.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { webRtcServer.on('workerclose', resolve); worker.close(); @@ -368,7 +370,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and transport is expect(onObserverWebRtcTransportHandled).toHaveBeenCalledWith(transport); expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(transport); - expect(transport.id).toBeType('string'); + expect(typeof transport.id).toBe('string'); expect(transport.closed).toBe(false); expect(transport.appData).toEqual({ foo: 'bar' }); @@ -472,7 +474,7 @@ test('router.createWebRtcTransport() with webRtcServer succeeds and webRtcServer .resolves .toMatchObject({ transportIds: [ transport.id ] }); - expect(transport.id).toBeType('string'); + expect(typeof transport.id).toBe('string'); expect(transport.closed).toBe(false); expect(transport.appData).toEqual({ foo: 'bar' }); diff --git a/node/tests/test-WebRtcTransport.js b/node/src/tests/test-WebRtcTransport.ts similarity index 89% rename from node/tests/test-WebRtcTransport.js rename to node/src/tests/test-WebRtcTransport.ts index 82575f18d06..2ad1b9f1ad6 100644 --- a/node/tests/test-WebRtcTransport.js +++ b/node/src/tests/test-WebRtcTransport.ts @@ -1,15 +1,14 @@ -const { toBeType } = require('jest-tobetype'); -const pickPort = require('pick-port'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +// @ts-ignore +import * as pickPort from 'pick-port'; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport: mediasoup.types.WebRtcTransport; -const mediaCodecs = +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -77,7 +76,7 @@ test('router.createWebRtcTransport() succeeds', async () => [ { ip: '127.0.0.1', announcedIp: '9.9.9.1' }, { ip: '0.0.0.0', announcedIp: '9.9.9.2' }, - { ip: '127.0.0.1', announcedIp: null } + { ip: '127.0.0.1', announcedIp: undefined } ], enableTcp : true, preferUdp : true, @@ -89,14 +88,14 @@ test('router.createWebRtcTransport() succeeds', async () => expect(onObserverNewTransport).toHaveBeenCalledTimes(1); expect(onObserverNewTransport).toHaveBeenCalledWith(transport1); - expect(transport1.id).toBeType('string'); + expect(typeof transport1.id).toBe('string'); expect(transport1.closed).toBe(false); expect(transport1.appData).toEqual({ foo: 'bar' }); expect(transport1.iceRole).toBe('controlled'); - expect(transport1.iceParameters).toBeType('object'); + expect(typeof transport1.iceParameters).toBe('object'); expect(transport1.iceParameters.iceLite).toBe(true); - expect(transport1.iceParameters.usernameFragment).toBeType('string'); - expect(transport1.iceParameters.password).toBeType('string'); + expect(typeof transport1.iceParameters.usernameFragment).toBe('string'); + expect(typeof transport1.iceParameters.password).toBe('string'); expect(transport1.sctpParameters).toMatchObject( { port : 5000, @@ -104,7 +103,7 @@ test('router.createWebRtcTransport() succeeds', async () => MIS : 2048, maxMessageSize : 1000000 }); - expect(transport1.iceCandidates).toBeType('array'); + expect(Array.isArray(transport1.iceCandidates)).toBe(true); expect(transport1.iceCandidates.length).toBe(6); const iceCandidates = transport1.iceCandidates; @@ -141,8 +140,8 @@ test('router.createWebRtcTransport() succeeds', async () => expect(transport1.iceState).toBe('new'); expect(transport1.iceSelectedTuple).toBeUndefined(); - expect(transport1.dtlsParameters).toBeType('object'); - expect(transport1.dtlsParameters.fingerprints).toBeType('array'); + expect(typeof transport1.dtlsParameters).toBe('object'); + expect(Array.isArray(transport1.dtlsParameters.fingerprints)).toBe(true); expect(transport1.dtlsParameters.role).toBe('auto'); expect(transport1.dtlsState).toBe('new'); expect(transport1.dtlsRemoteCert).toBeUndefined(); @@ -163,19 +162,21 @@ test('router.createWebRtcTransport() succeeds', async () => expect(data1.dtlsState).toBe(transport1.dtlsState); expect(data1.sctpParameters).toEqual(transport1.sctpParameters); expect(data1.sctpState).toBe(transport1.sctpState); - expect(data1.recvRtpHeaderExtensions).toBeType('object'); - expect(data1.rtpListener).toBeType('object'); + expect(typeof data1.recvRtpHeaderExtensions).toBe('object'); + expect(typeof data1.rtpListener).toBe('object'); transport1.close(); expect(transport1.closed).toBe(true); - await expect(router.createWebRtcTransport({ listenIps: [ '127.0.0.1' ] })) - .resolves - .toBeType('object'); + const anotherTransport = await router.createWebRtcTransport( + { listenIps: [ '127.0.0.1' ] }); + + expect(typeof anotherTransport).toBe('object'); }, 2000); test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(router.createWebRtcTransport({})) .rejects .toThrow(TypeError); @@ -184,10 +185,12 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createWebRtcTransport({ listenIps: [ 123 ] })) .rejects .toThrow(TypeError); + // @ts-ignore await expect(router.createWebRtcTransport({ listenIps: '127.0.0.1' })) .rejects .toThrow(TypeError); @@ -195,6 +198,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError await expect(router.createWebRtcTransport( { listenIps : [ '127.0.0.1' ], + // @ts-ignore appData : 'NOT-AN-OBJECT' })) .rejects @@ -204,6 +208,7 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError { listenIps : [ '127.0.0.1' ], enableSctp : true, + // @ts-ignore numSctpStreams : 'foo' })) .rejects @@ -221,11 +226,11 @@ test('webRtcTransport.getStats() succeeds', async () => { const data = await transport.getStats(); - expect(data).toBeType('array'); + expect(Array.isArray(data)).toBe(true); expect(data.length).toBe(1); expect(data[0].type).toBe('webrtc-transport'); expect(data[0].transportId).toBe(transport.id); - expect(data[0].timestamp).toBeType('number'); + expect(typeof data[0].timestamp).toBe('number'); expect(data[0].iceRole).toBe('controlled'); expect(data[0].iceState).toBe('new'); expect(data[0].dtlsState).toBe('new'); @@ -250,7 +255,7 @@ test('webRtcTransport.getStats() succeeds', async () => test('webRtcTransport.connect() succeeds', async () => { - const dtlsRemoteParameters = + const dtlsRemoteParameters: mediasoup.types.DtlsParameters = { fingerprints : [ @@ -276,8 +281,9 @@ test('webRtcTransport.connect() succeeds', async () => test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { - let dtlsRemoteParameters; + let dtlsRemoteParameters: mediasoup.types.DtlsParameters; + // @ts-ignore await expect(transport.connect({})) .rejects .toThrow(TypeError); @@ -307,6 +313,7 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' } ], + // @ts-ignore role : 'chicken' }; @@ -359,8 +366,8 @@ test('webRtcTransport.restartIce() succeeds', async () => iceLite : true }); - expect(transport.iceParameters.usernameFragment).toBeType('string'); - expect(transport.iceParameters.password).toBeType('string'); + expect(typeof transport.iceParameters.usernameFragment).toBe('string'); + expect(typeof transport.iceParameters.password).toBe('string'); expect(transport.iceParameters.usernameFragment) .not.toBe(previousIceUsernameFragment); expect(transport.iceParameters.password).not.toBe(previousIcePassword); @@ -368,6 +375,7 @@ test('webRtcTransport.restartIce() succeeds', async () => test('transport.enableTraceEvent() succeed', async () => { + // @ts-ignore await transport.enableTraceEvent([ 'foo', 'probation' ]); await expect(transport.dump()) .resolves @@ -378,6 +386,7 @@ test('transport.enableTraceEvent() succeed', async () => .resolves .toMatchObject({ traceEventTypes: '' }); + // @ts-ignore await transport.enableTraceEvent([ 'probation', 'FOO', 'bwe', 'BAR' ]); await expect(transport.dump()) .resolves @@ -391,14 +400,17 @@ test('transport.enableTraceEvent() succeed', async () => test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { + // @ts-ignore await expect(transport.enableTraceEvent(123)) .rejects .toThrow(TypeError); + // @ts-ignore await expect(transport.enableTraceEvent('probation')) .rejects .toThrow(TypeError); + // @ts-ignore await expect(transport.enableTraceEvent([ 'probation', 123.123 ])) .rejects .toThrow(TypeError); @@ -475,15 +487,16 @@ test('WebRtcTransport methods reject if closed', async () => .rejects .toThrow(Error); + // @ts-ignore await expect(transport.connect({})) .rejects .toThrow(Error); - await expect(transport.setMaxIncomingBitrate()) + await expect(transport.setMaxIncomingBitrate(200000)) .rejects .toThrow(Error); - await expect(transport.setMaxOutgoingBitrate()) + await expect(transport.setMaxOutgoingBitrate(200000)) .rejects .toThrow(Error); @@ -520,7 +533,7 @@ test('WebRtcTransport emits "routerclose" if Router is closed', async () => transport2.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { transport2.on('routerclose', resolve); router2.close(); @@ -540,7 +553,7 @@ test('WebRtcTransport emits "routerclose" if Worker is closed', async () => transport.observer.once('close', onObserverClose); - await new Promise((resolve) => + await new Promise((resolve) => { transport.on('routerclose', resolve); worker.close(); diff --git a/node/tests/test-Worker.js b/node/src/tests/test-Worker.ts similarity index 90% rename from node/tests/test-Worker.js rename to node/src/tests/test-Worker.ts index 946c3de4555..b640196460b 100644 --- a/node/tests/test-Worker.js +++ b/node/src/tests/test-Worker.ts @@ -1,14 +1,12 @@ -const os = require('os'); -const process = require('process'); -const path = require('path'); -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { createWorker, observer } = mediasoup; -const { InvalidStateError } = require('../lib/errors'); +import * as os from 'os'; +import * as process from 'process'; +import * as path from 'path'; +import * as mediasoup from '../'; +import { InvalidStateError } from '../errors'; -expect.extend({ toBeType }); +const { createWorker, observer } = mediasoup; -let worker; +let worker: mediasoup.types.Worker; beforeEach(() => worker && !worker.closed && worker.close()); afterEach(() => worker && !worker.closed && worker.close()); @@ -23,8 +21,8 @@ test('createWorker() succeeds', async () => expect(onObserverNewWorker).toHaveBeenCalledTimes(1); expect(onObserverNewWorker).toHaveBeenCalledWith(worker); - expect(worker).toBeType('object'); - expect(worker.pid).toBeType('number'); + expect(worker.constructor.name).toBe('Worker'); + expect(typeof worker.pid).toBe('number'); expect(worker.closed).toBe(false); expect(worker.died).toBe(false); @@ -44,8 +42,8 @@ test('createWorker() succeeds', async () => dtlsPrivateKeyFile : path.join(__dirname, 'data', 'dtls-key.pem'), appData : { bar: 456 } }); - expect(worker).toBeType('object'); - expect(worker.pid).toBeType('number'); + expect(worker.constructor.name).toBe('Worker'); + expect(typeof worker.pid).toBe('number'); expect(worker.closed).toBe(false); expect(worker.died).toBe(false); expect(worker.appData).toEqual({ bar: 456 }); @@ -58,6 +56,7 @@ test('createWorker() succeeds', async () => test('createWorker() with wrong settings rejects with TypeError', async () => { + // @ts-ignore await expect(createWorker({ logLevel: 'chicken' })) .rejects .toThrow(TypeError); @@ -79,6 +78,7 @@ test('createWorker() with wrong settings rejects with TypeError', async () => .rejects .toThrow(TypeError); + // @ts-ignore await expect(createWorker({ appData: 'NOT-AN-OBJECT' })) .rejects .toThrow(TypeError); @@ -99,6 +99,7 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async { worker = await createWorker(); + // @ts-ignore await expect(worker.updateSettings({ logLevel: 'chicken' })) .rejects .toThrow(TypeError); @@ -179,8 +180,8 @@ test('worker.close() succeeds', async () => test('Worker emits "died" if worker process died unexpectedly', async () => { - let onDied; - let onObserverClose; + let onDied: ReturnType; + let onObserverClose: ReturnType; worker = await createWorker({ logLevel: 'warn' }); onDied = jest.fn(); @@ -188,7 +189,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => worker.observer.once('close', onObserverClose); - await new Promise((resolve, reject) => + await new Promise((resolve, reject) => { worker.on('died', () => { @@ -224,7 +225,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => worker.observer.once('close', onObserverClose); - await new Promise((resolve, reject) => + await new Promise((resolve, reject) => { worker.on('died', () => { @@ -260,7 +261,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => worker.observer.once('close', onObserverClose); - await new Promise((resolve, reject) => + await new Promise((resolve, reject) => { worker.on('died', () => { @@ -299,7 +300,7 @@ test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () = worker = await createWorker({ logLevel: 'warn' }); - await new Promise((resolve, reject) => + await new Promise((resolve, reject) => { worker.on('died', reject); diff --git a/node/tests/test-mediasoup.js b/node/src/tests/test-mediasoup.ts similarity index 80% rename from node/tests/test-mediasoup.js rename to node/src/tests/test-mediasoup.ts index f3f61d6a746..706341748e2 100644 --- a/node/tests/test-mediasoup.js +++ b/node/src/tests/test-mediasoup.ts @@ -1,28 +1,19 @@ -const { toBeType } = require('jest-tobetype'); -const pkg = require('../../package.json'); -const mediasoup = require('../lib/'); +import * as mediasoup from '../'; + const { - version, getSupportedRtpCapabilities, parseScalabilityMode } = mediasoup; -expect.extend({ toBeType }); - -test('mediasoup.version exposes the package version', () => -{ - expect(version).toBeType('string'); - expect(version).toBe(pkg.version); -}, 500); - test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabilities', () => { const rtpCapabilities = getSupportedRtpCapabilities(); - expect(rtpCapabilities).toBeType('object'); + expect(typeof rtpCapabilities).toBe('object'); // Mangle retrieved codecs to check that, if called again, // getSupportedRtpCapabilities() returns a cloned object. + // @ts-ignore rtpCapabilities.codecs = 'bar'; const rtpCapabilities2 = getSupportedRtpCapabilities(); @@ -44,7 +35,7 @@ test('parseScalabilityMode() works', () => expect(parseScalabilityMode('foo')) .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); - expect(parseScalabilityMode(null)) + expect(parseScalabilityMode(undefined)) .toEqual({ spatialLayers: 1, temporalLayers: 1, ksvc: false }); expect(parseScalabilityMode('S0T3')) diff --git a/node/tests/test-multiopus.js b/node/src/tests/test-multiopus.ts similarity index 88% rename from node/tests/test-multiopus.js rename to node/src/tests/test-multiopus.ts index 7b9268b8d94..b1e3a260ed5 100644 --- a/node/tests/test-multiopus.js +++ b/node/src/tests/test-multiopus.ts @@ -1,15 +1,14 @@ -const { toBeType } = require('jest-tobetype'); -const mediasoup = require('../lib/'); -const { UnsupportedError } = require('../lib/errors'); -const { createWorker } = mediasoup; +import * as mediasoup from '../'; +import { UnsupportedError } from '../errors'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; -let worker; -let router; -let transport; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport: mediasoup.types.WebRtcTransport; -const mediaCodecs = [ +const mediaCodecs: mediasoup.types.RtpCodecCapability[] = +[ { kind : 'audio', mimeType : 'audio/multiopus', @@ -25,7 +24,8 @@ const mediaCodecs = [ } ]; -const audioProducerOptions = { +const audioProducerParameters: mediasoup.types.ProducerOptions = +{ kind : 'audio', rtpParameters : { @@ -60,7 +60,8 @@ const audioProducerOptions = { } }; -const consumerDeviceCapabilities = { +const consumerDeviceCapabilities: mediasoup.types.RtpCapabilities = +{ codecs : [ { @@ -114,7 +115,7 @@ afterAll(() => worker.close()); test('produce/consume succeeds', async () => { - const audioProducer = await transport.produce(audioProducerOptions); + const audioProducer = await transport.produce(audioProducerParameters); expect(audioProducer.rtpParameters.codecs).toEqual([ { @@ -220,9 +221,9 @@ test('fails to produce wrong parameters', async () => test('fails to consume wrong channels', async () => { - const audioProducer = await transport.produce(audioProducerOptions); + const audioProducer = await transport.produce(audioProducerParameters); - const localConsumerDeviceCapabilities = { + const localConsumerDeviceCapabilities: mediasoup.types.RtpCapabilities = { codecs : [ { diff --git a/node/tests/test-node-sctp.js b/node/src/tests/test-node-sctp.ts similarity index 81% rename from node/tests/test-node-sctp.js rename to node/src/tests/test-node-sctp.ts index e3b84746f5b..2aca0a4cfb2 100644 --- a/node/tests/test-node-sctp.js +++ b/node/src/tests/test-node-sctp.ts @@ -1,23 +1,22 @@ -const { toBeType } = require('jest-tobetype'); -const dgram = require('dgram'); -const sctp = require('sctp'); -const mediasoup = require('../lib/'); -const { createWorker } = mediasoup; +import * as dgram from 'dgram'; +// @ts-ignore +import * as sctp from 'sctp'; +import * as mediasoup from '../'; -expect.extend({ toBeType }); +const { createWorker } = mediasoup; // Set node-sctp default PMTU to 1200. sctp.defaults({ PMTU: 1200 }); -let worker; -let router; -let transport; -let dataProducer; -let dataConsumer; -let udpSocket; -let sctpSocket; -let sctpSendStreamId; -let sctpSendStream; +let worker: mediasoup.types.Worker; +let router: mediasoup.types.Router; +let transport: mediasoup.types.PlainTransport; +let dataProducer: mediasoup.types.DataProducer; +let dataConsumer: mediasoup.types.DataConsumer; +let udpSocket: dgram.Socket; +let sctpSocket: any; +let sctpSendStreamId: number; +let sctpSendStream: any; beforeAll(async () => { @@ -34,18 +33,19 @@ beforeAll(async () => // Node UDP socket for SCTP. udpSocket = dgram.createSocket({ type: 'udp4' }); - await new Promise((resolve) => udpSocket.bind(0, '127.0.0.1', resolve)); + await new Promise((resolve) => udpSocket.bind(0, '127.0.0.1', resolve)); const remoteUdpIp = transport.tuple.localIp; const remoteUdpPort = transport.tuple.localPort; - const { OS, MIS } = transport.sctpParameters; + const { OS, MIS } = transport.sctpParameters!; // Use UDP connected socket if Node >= 12. if (typeof udpSocket.connect === 'function') { - await new Promise((resolve, reject) => + await new Promise((resolve, reject) => { - udpSocket.connect(remoteUdpPort, remoteUdpIp, (error) => + // @ts-ignore + udpSocket.connect(remoteUdpPort, remoteUdpIp, (error: Error) => { if (error) { @@ -88,8 +88,8 @@ beforeAll(async () => // Wait for the SCTP association to be open. await Promise.race( [ - new Promise((resolve) => sctpSocket.on('connect', resolve)), - new Promise((resolve, reject) => ( + new Promise((resolve) => sctpSocket.on('connect', resolve)), + new Promise((resolve, reject) => ( setTimeout(() => reject(new Error('SCTP connection timeout')), 3000) )) ]); @@ -133,9 +133,9 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn let lastRecvMessageId = 0; // It must be zero because it's the first DataConsumer on the transport. - expect(dataConsumer.sctpStreamParameters.streamId).toBe(0); + expect(dataConsumer.sctpStreamParameters?.streamId).toBe(0); - await new Promise((resolve) => + await new Promise((resolve) => { // Send SCTP messages over the sctpSendStream created above. const interval = setInterval(() => @@ -146,11 +146,13 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn // Set ppid of type WebRTC DataChannel string. if (id < numMessages / 2) { + // @ts-ignore data.ppid = sctp.PPID.WEBRTC_STRING; } // Set ppid of type WebRTC DataChannel binary. else { + // @ts-ignore data.ppid = sctp.PPID.WEBRTC_BINARY; } @@ -164,13 +166,15 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn sctpSocket.on('stream', onStream); // Handle the generated SCTP incoming stream and SCTP messages receives on it. + // @ts-ignore sctpSocket.on('stream', (stream, streamId) => { // It must be zero because it's the first SCTP incoming stream (so first // DataConsumer). expect(streamId).toBe(0); - stream.on('data', (data) => + // @ts-ignore + stream.on('data', (data: Buffer) => { recvMessageBytes += data.byteLength; @@ -183,9 +187,15 @@ test('ordered DataProducer delivers all SCTP messages to the DataConsumer', asyn } if (id < numMessages / 2) + { + // @ts-ignore expect(data.ppid).toBe(sctp.PPID.WEBRTC_STRING); + } else + { + // @ts-ignore expect(data.ppid).toBe(sctp.PPID.WEBRTC_BINARY); + } expect(id).toBe(++lastRecvMessageId); }); diff --git a/node/tests/test-ortc.js b/node/src/tests/test-ortc.ts similarity index 81% rename from node/tests/test-ortc.js rename to node/src/tests/test-ortc.ts index 11ff14d322e..abe9558956e 100644 --- a/node/tests/test-ortc.js +++ b/node/src/tests/test-ortc.ts @@ -1,12 +1,10 @@ -const { toBeType } = require('jest-tobetype'); -const { UnsupportedError } = require('../lib/errors'); -const ortc = require('../lib/ortc'); - -expect.extend({ toBeType }); +import * as mediasoup from '../'; +import * as ortc from '../ortc'; +import { UnsupportedError } from '../errors'; test('generateRouterRtpCapabilities() succeeds', () => { - const mediaCodecs = + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -41,10 +39,10 @@ test('generateRouterRtpCapabilities() succeeds', () => const rtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); - expect(rtpCapabilities.codecs.length).toBe(5); + expect(rtpCapabilities.codecs?.length).toBe(5); // opus. - expect(rtpCapabilities.codecs[0]).toEqual( + expect(rtpCapabilities.codecs?.[0]).toEqual( { kind : 'audio', mimeType : 'audio/opus', @@ -63,7 +61,7 @@ test('generateRouterRtpCapabilities() succeeds', () => }); // VP8. - expect(rtpCapabilities.codecs[1]).toEqual( + expect(rtpCapabilities.codecs?.[1]).toEqual( { kind : 'video', mimeType : 'video/VP8', @@ -81,7 +79,7 @@ test('generateRouterRtpCapabilities() succeeds', () => }); // VP8 RTX. - expect(rtpCapabilities.codecs[2]).toEqual( + expect(rtpCapabilities.codecs?.[2]).toEqual( { kind : 'video', mimeType : 'video/rtx', @@ -95,7 +93,7 @@ test('generateRouterRtpCapabilities() succeeds', () => }); // H264. - expect(rtpCapabilities.codecs[3]).toEqual( + expect(rtpCapabilities.codecs?.[3]).toEqual( { kind : 'video', mimeType : 'video/H264', @@ -121,7 +119,7 @@ test('generateRouterRtpCapabilities() succeeds', () => }); // H264 RTX. - expect(rtpCapabilities.codecs[4]).toEqual( + expect(rtpCapabilities.codecs?.[4]).toEqual( { kind : 'video', mimeType : 'video/rtx', @@ -137,7 +135,7 @@ test('generateRouterRtpCapabilities() succeeds', () => test('generateRouterRtpCapabilities() with unsupported codecs throws UnsupportedError', () => { - let mediaCodecs; + let mediaCodecs: mediasoup.types.RtpCodecCapability[]; mediaCodecs = [ @@ -168,7 +166,7 @@ test('generateRouterRtpCapabilities() with unsupported codecs throws Unsupported test('generateRouterRtpCapabilities() with too many codecs throws', () => { - const mediaCodecs = []; + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = []; for (let i = 0; i < 100; ++i) { @@ -187,7 +185,7 @@ test('generateRouterRtpCapabilities() with too many codecs throws', () => test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsumerRtpParameters() and getPipeConsumerRtpParameters() succeed', () => { - const mediaCodecs = + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', @@ -211,7 +209,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum const routerRtpCapabilities = ortc.generateRouterRtpCapabilities(mediaCodecs); - const rtpParameters = + const rtpParameters: mediasoup.types.RtpParameters = { codecs : [ @@ -291,13 +289,13 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(rtpMapping.encodings[0].ssrc).toBe(11111111); expect(rtpMapping.encodings[0].rid).toBeUndefined(); - expect(rtpMapping.encodings[0].mappedSsrc).toBeType('number'); + expect(typeof rtpMapping.encodings[0].mappedSsrc).toBe('number'); expect(rtpMapping.encodings[1].ssrc).toBe(21111111); expect(rtpMapping.encodings[1].rid).toBeUndefined(); - expect(rtpMapping.encodings[1].mappedSsrc).toBeType('number'); + expect(typeof rtpMapping.encodings[1].mappedSsrc).toBe('number'); expect(rtpMapping.encodings[2].ssrc).toBeUndefined(); expect(rtpMapping.encodings[2].rid).toBe('high'); - expect(rtpMapping.encodings[2].mappedSsrc).toBeType('number'); + expect(typeof rtpMapping.encodings[2].mappedSsrc).toBe('number'); const consumableRtpParameters = ortc.getConsumableRtpParameters( 'video', rtpParameters, routerRtpCapabilities, rtpMapping); @@ -317,19 +315,19 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumableRtpParameters.codecs[1].clockRate).toBe(90000); expect(consumableRtpParameters.codecs[1].parameters).toEqual({ apt: 101 }); - expect(consumableRtpParameters.encodings[0]).toEqual( + expect(consumableRtpParameters.encodings?.[0]).toEqual( { ssrc : rtpMapping.encodings[0].mappedSsrc, maxBitrate : 111111, scalabilityMode : 'L1T3' }); - expect(consumableRtpParameters.encodings[1]).toEqual( + expect(consumableRtpParameters.encodings?.[1]).toEqual( { ssrc : rtpMapping.encodings[1].mappedSsrc, maxBitrate : 222222, scalabilityMode : 'L1T3' }); - expect(consumableRtpParameters.encodings[2]).toEqual( + expect(consumableRtpParameters.encodings?.[2]).toEqual( { ssrc : rtpMapping.encodings[2].mappedSsrc, maxBitrate : 333333, @@ -338,12 +336,12 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumableRtpParameters.rtcp).toEqual( { - cname : rtpParameters.rtcp.cname, + cname : rtpParameters.rtcp?.cname, reducedSize : true, mux : true }); - const remoteRtpCapabilities = + const remoteRtpCapabilities: mediasoup.types.RtpCapabilities = { codecs : [ @@ -467,12 +465,12 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum rtcpFeedback : [] }); - expect(consumerRtpParameters.encodings.length).toBe(1); - expect(consumerRtpParameters.encodings[0].ssrc).toBeType('number'); - expect(consumerRtpParameters.encodings[0].rtx).toBeType('object'); - expect(consumerRtpParameters.encodings[0].rtx.ssrc).toBeType('number'); - expect(consumerRtpParameters.encodings[0].scalabilityMode).toBe('S3T3'); - expect(consumerRtpParameters.encodings[0].maxBitrate).toBe(333333); + expect(consumerRtpParameters.encodings?.length).toBe(1); + expect(typeof consumerRtpParameters.encodings?.[0].ssrc).toBe('number'); + expect(typeof consumerRtpParameters.encodings?.[0].rtx).toBe('object'); + expect(typeof consumerRtpParameters.encodings?.[0].rtx?.ssrc).toBe('number'); + expect(consumerRtpParameters.encodings?.[0].scalabilityMode).toBe('S3T3'); + expect(consumerRtpParameters.encodings?.[0].maxBitrate).toBe(333333); expect(consumerRtpParameters.headerExtensions).toEqual( [ @@ -498,7 +496,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum expect(consumerRtpParameters.rtcp).toEqual( { - cname : rtpParameters.rtcp.cname, + cname : rtpParameters.rtcp?.cname, reducedSize : true, mux : true }); @@ -525,23 +523,23 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum ] }); - expect(pipeConsumerRtpParameters.encodings.length).toBe(3); - expect(pipeConsumerRtpParameters.encodings[0].ssrc).toBeType('number'); - expect(pipeConsumerRtpParameters.encodings[0].rtx).toBeUndefined(); - expect(pipeConsumerRtpParameters.encodings[0].maxBitrate).toBeType('number'); - expect(pipeConsumerRtpParameters.encodings[0].scalabilityMode).toBe('L1T3'); - expect(pipeConsumerRtpParameters.encodings[1].ssrc).toBeType('number'); - expect(pipeConsumerRtpParameters.encodings[1].rtx).toBeUndefined(); - expect(pipeConsumerRtpParameters.encodings[1].maxBitrate).toBeType('number'); - expect(pipeConsumerRtpParameters.encodings[1].scalabilityMode).toBe('L1T3'); - expect(pipeConsumerRtpParameters.encodings[2].ssrc).toBeType('number'); - expect(pipeConsumerRtpParameters.encodings[2].rtx).toBeUndefined(); - expect(pipeConsumerRtpParameters.encodings[2].maxBitrate).toBeType('number'); - expect(pipeConsumerRtpParameters.encodings[2].scalabilityMode).toBe('L1T3'); + expect(pipeConsumerRtpParameters.encodings?.length).toBe(3); + expect(typeof pipeConsumerRtpParameters.encodings?.[0].ssrc).toBe('number'); + expect(pipeConsumerRtpParameters.encodings?.[0].rtx).toBeUndefined(); + expect(typeof pipeConsumerRtpParameters.encodings?.[0].maxBitrate).toBe('number'); + expect(pipeConsumerRtpParameters.encodings?.[0].scalabilityMode).toBe('L1T3'); + expect(typeof pipeConsumerRtpParameters.encodings?.[1].ssrc).toBe('number'); + expect(pipeConsumerRtpParameters.encodings?.[1].rtx).toBeUndefined(); + expect(typeof pipeConsumerRtpParameters.encodings?.[1].maxBitrate).toBe('number'); + expect(pipeConsumerRtpParameters.encodings?.[1].scalabilityMode).toBe('L1T3'); + expect(typeof pipeConsumerRtpParameters.encodings?.[2].ssrc).toBe('number'); + expect(pipeConsumerRtpParameters.encodings?.[2].rtx).toBeUndefined(); + expect(typeof pipeConsumerRtpParameters.encodings?.[2].maxBitrate).toBe('number'); + expect(pipeConsumerRtpParameters.encodings?.[2].scalabilityMode).toBe('L1T3'); expect(pipeConsumerRtpParameters.rtcp).toEqual( { - cname : rtpParameters.rtcp.cname, + cname : rtpParameters.rtcp?.cname, reducedSize : true, mux : true }); @@ -549,7 +547,7 @@ test('getProducerRtpParametersMapping(), getConsumableRtpParameters(), getConsum test('getProducerRtpParametersMapping() with incompatible params throws UnsupportedError', () => { - const mediaCodecs = + const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [ { kind : 'audio', diff --git a/npm-scripts.js b/npm-scripts.js index 819dc028e18..fb48ace5c9e 100644 --- a/npm-scripts.js +++ b/npm-scripts.js @@ -256,22 +256,29 @@ switch (task) break; } - case 'release': + case 'install-clang-tools': { - execute('npm run typescript:build'); - execute('npm run lint'); - execute('npm run test'); - execute(`git commit -am '${version}'`); - execute(`git tag -a ${version} -m '${version}'`); - execute(`git push origin v${MAYOR_VERSION} && git push origin --tags`); - execute('npm publish'); + executeCmd('npm ci --prefix worker/scripts'); break; } - case 'install-clang-tools': + case 'release:check': { - executeCmd('npm ci --prefix worker/scripts'); + checkRelease(); + + break; + } + + case 'release': + { + checkRelease(); + executeCmd('git diff --quiet || exit 1'); + executeCmd(`git commit -am '${version}'`); + executeCmd(`git tag -a ${version} -m '${version}'`); + executeCmd(`git push origin v${MAYOR_VERSION}`); + executeCmd(`git push origin '${version}'`); + executeCmd('npm publish'); break; } @@ -359,7 +366,7 @@ function lintNode() { console.log('npm-scripts.js [INFO] lintNode()'); - executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.js node/tests worker/scripts/gulpfile.js'); + executeCmd('eslint -c node/.eslintrc.js --max-warnings 0 node/src node/.eslintrc.js npm-scripts.js worker/scripts/gulpfile.js'); } function lintWorker() @@ -375,7 +382,7 @@ function testNode() if (!process.env.TEST_FILE) { - executeCmd('jest'); + executeCmd('jest --detectOpenHandles'); } else { @@ -400,6 +407,20 @@ function installNodeDeps() executeCmd('npm install --package-lock-only --ignore-scripts'); } +function checkRelease() +{ + console.log('npm-scripts.js [INFO] checkRelease()'); + + installNodeDeps(); + buildTypescript(/* force */ true); + replaceVersion(); + buildWorker(); + lintNode(); + lintWorker(); + testNode(); + testWorker(); +} + function executeCmd(command, exitOnError = true) { console.log(`npm-scripts.js [INFO] executeCmd(): ${command}`); @@ -412,7 +433,13 @@ function executeCmd(command, exitOnError = true) { if (exitOnError) { + console.error(`npm-scripts.js [ERROR] executeCmd() failed, exiting: ${error}`); + process.exit(1); } + else + { + console.log(`npm-scripts.js [INFO] executeCmd() failed, ignoring: ${error}`); + } } } diff --git a/package-lock.json b/package-lock.json index 7dd286e7ddd..43d8d47fc42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ }, "devDependencies": { "@types/debug": "^4.1.7", + "@types/jest": "^29.2.3", "@types/node": "^18.11.9", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^5.43.0", @@ -24,10 +25,10 @@ "eslint": "^8.27.0", "eslint-plugin-jest": "^27.1.5", "jest": "^29.3.1", - "jest-tobetype": "^1.2.3", "open-cli": "^7.1.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", + "ts-jest": "^29.0.3", "tsc-watch": "^5.0.3", "typescript": "^4.9.3" }, @@ -1278,6 +1279,16 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/jest": { + "version": "29.2.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.3.tgz", + "integrity": "sha512-6XwoEbmatfyoCjWRX7z0fKMmgYKe9+/HrviJ5k0X/tjJWHGAezZOfYaxqQKuzG/TvQyr+ktjm4jgbk0s4/oF2w==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -1806,6 +1817,18 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -3722,189 +3745,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-tobetype": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-tobetype/-/jest-tobetype-1.2.3.tgz", - "integrity": "sha512-9wVkY9lDW4BhcUc0Hpc0hq7n1i/erZW59RbGMl+oAi4IKPi4YtaXHdJgQg0QMDPWtK5PiM82hw6jPbVjH61Z5A==", - "dev": true, - "dependencies": { - "jest-get-type": "^24.3.0", - "jest-matcher-utils": "^24.7.0" - } - }, - "node_modules/jest-tobetype/node_modules/@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-tobetype/node_modules/@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/jest-tobetype/node_modules/@types/yargs": { - "version": "13.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", - "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest-tobetype/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-tobetype/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jest-tobetype/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jest-tobetype/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/jest-tobetype/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/jest-tobetype/node_modules/diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-tobetype/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/jest-tobetype/node_modules/jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, - "dependencies": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-tobetype/node_modules/jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-tobetype/node_modules/jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "dependencies": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-tobetype/node_modules/pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "dependencies": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jest-tobetype/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/jest-tobetype/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/jest-util": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", @@ -4136,6 +3976,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4178,6 +4024,12 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -5510,6 +5362,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts-jest": { + "version": "29.0.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", + "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.1", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/tsc-watch": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-5.0.3.tgz", @@ -6805,6 +6709,16 @@ "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "29.2.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.3.tgz", + "integrity": "sha512-6XwoEbmatfyoCjWRX7z0fKMmgYKe9+/HrviJ5k0X/tjJWHGAezZOfYaxqQKuzG/TvQyr+ktjm4jgbk0s4/oF2w==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -7164,6 +7078,15 @@ "update-browserslist-db": "^1.0.9" } }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -8565,158 +8488,6 @@ "semver": "^7.3.5" } }, - "jest-tobetype": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-tobetype/-/jest-tobetype-1.2.3.tgz", - "integrity": "sha512-9wVkY9lDW4BhcUc0Hpc0hq7n1i/erZW59RbGMl+oAi4IKPi4YtaXHdJgQg0QMDPWtK5PiM82hw6jPbVjH61Z5A==", - "dev": true, - "requires": { - "jest-get-type": "^24.3.0", - "jest-matcher-utils": "^24.7.0" - }, - "dependencies": { - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "@types/yargs": { - "version": "13.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", - "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "jest-util": { "version": "29.3.1", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", @@ -8892,6 +8663,12 @@ "p-locate": "^5.0.0" } }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -8924,6 +8701,12 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -9862,6 +9645,30 @@ "integrity": "sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==", "dev": true }, + "ts-jest": { + "version": "29.0.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", + "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.1", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "^21.0.1" + }, + "dependencies": { + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, "tsc-watch": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-5.0.3.tgz", diff --git a/package.json b/package.json index a557d834ee8..996c6982c99 100644 --- a/package.json +++ b/package.json @@ -83,12 +83,17 @@ "coverage:node": "node npm-scripts.js coverage:node", "install-deps:node": "node npm-scripts.js install-deps:node", "install-clang-tools": "node npm-scripts.js install-clang-tools", + "release:check": "node npm-scripts.js release:check", "release": "node npm-scripts.js release" }, "jest": { "verbose": true, "testEnvironment": "node", - "testRegex": "node/tests/test.*\\.js" + "testRegex": "node/src/tests/test-.*\\.ts", + "transform": { + "^.*\\.ts$": [ "ts-jest", { "diagnostics": { "ignoreCodes": [ "TS151001" ] } } ] + }, + "cacheDirectory": ".cache/jest" }, "dependencies": { "debug": "^4.3.4", @@ -98,6 +103,7 @@ }, "devDependencies": { "@types/debug": "^4.1.7", + "@types/jest": "^29.2.3", "@types/node": "^18.11.9", "@types/uuid": "^8.3.4", "@typescript-eslint/eslint-plugin": "^5.43.0", @@ -105,10 +111,10 @@ "eslint": "^8.27.0", "eslint-plugin-jest": "^27.1.5", "jest": "^29.3.1", - "jest-tobetype": "^1.2.3", "open-cli": "^7.1.0", "pick-port": "^1.0.1", "sctp": "^1.0.0", + "ts-jest": "^29.0.3", "tsc-watch": "^5.0.3", "typescript": "^4.9.3" }