From 0f2549728dd661e41f7cc37d96b0bef20b825c38 Mon Sep 17 00:00:00 2001 From: Joyce Ma <43423318+PikaJoyce@users.noreply.github.com> Date: Tue, 8 Mar 2022 14:41:50 -0800 Subject: [PATCH] Prep 2.21.0 release (#1729) * Merge Preflight and PlanB removal feature branch (#1702) * VIDEO-7728 | Better Preflight Errors (#1689) * Adding better errors on preflight * lint * Update docs * Changelog * Update docs * Convert error to string * Adding timestamp to progress events * Properly raising signaling errors * lint * Update tests * Mak's feedback * Update test * Feature/remove plan b (#1697) * VIDEO-6587 | Remove Plan B in SDK (#1656) * Initial implementation. * Fixing integration tests * Updating unit tests * Adding back unit test job * Removing unneeded case * Fix build * Adding rename suggestion Co-authored-by: Manjesh Malavalli * Adding changelog * Update CHANGELOG.md Co-authored-by: Manjesh Malavalli * Adding ticket number Co-authored-by: Manjesh Malavalli Co-authored-by: Manjesh Malavalli * Move changelog to 2.20.0 section * 2.20.0-rc1 * 2.20.0-dev Co-authored-by: Manjesh Malavalli Co-authored-by: Manjesh Malavalli Co-authored-by: twilio-ci * Fix unit test from merge * 2.20.0-rc2 * 2.20.0-dev * Update doc * Update changelog Co-authored-by: Manjesh Malavalli Co-authored-by: Manjesh Malavalli Co-authored-by: twilio-ci * Removing framework tests (#1700) * Convert createLocalTracks to TS (#1694) * VIDEO-7714 - Convert createLocalTracks to TypeScript Co-authored-by: joma Co-authored-by: charliesantos * Update @twilio/webrtc to 4.6.0-rc1 (#1705) * Update @twilio-webrtc to RC Co-authored-by: joma * 2.21.0-rc1 * 2.21.0-dev * merge from master * VIDEO-8791 - Adding extra information into CHANGELOG (#1716) * Adding extra information into CHANGELOG * 2.21.0-rc2 * 2.21.0-dev * VIDEO-8647 - Fixing Chrome Docker Image (#1718) * VIDEO-8647 Fixing docker images build for Chrome * VIDEO-8954: Adding in extra links and details to the CHANGELOG entry (#1722) * VIDEO-8954 - Adding in extra links and details to the CHANGELOG entry * VIDEO-8647 - Fixing Chrome Docker Image (#1718) (#1721) (#1728) * VIDEO-8647 Fixing docker images build for Chrome * prep 2.21.0 release Co-authored-by: Charlemagne Santos Co-authored-by: Manjesh Malavalli Co-authored-by: Manjesh Malavalli Co-authored-by: twilio-ci Co-authored-by: Makarand Patwardhan --- .circleci/config.yml | 17 --- CHANGELOG.md | 18 +++ README.md | 17 ++- lib/connect.js | 2 - lib/createlocaltrack.js | 2 - ...atelocaltracks.js => createlocaltracks.ts} | 109 +++++++++++------- lib/index.ts | 28 +++-- package.json | 8 +- scripts/docs.js | 2 +- test/integration/index.js | 2 +- test/integration/spec/audioonlyrooms.js | 2 +- .../spec/bandwidthprofile/publisherhints.js | 4 +- .../spec/bandwidthprofile/regressions.js | 4 +- .../spec/bandwidthprofile/renderhints.js | 4 +- .../spec/bandwidthprofile/video.js | 5 +- test/integration/spec/connect.js | 4 +- test/integration/spec/leaktests.js | 3 +- test/integration/spec/localtracks.js | 5 +- test/integration/spec/logger.js | 2 +- test/integration/spec/remotetracks.js | 3 +- test/integration/spec/rest.js | 2 +- test/integration/spec/room.js | 3 +- test/lib/util.js | 2 +- test/unit/index.js | 1 - test/unit/index.ts | 3 +- test/unit/spec/connect.js | 5 + ...atelocaltracks.js => createlocaltracks.ts} | 10 +- test/unit/spec/util/support.js | 23 ++++ tsdef/ConnectOptionsInternal.d.ts | 5 + tsdef/twilio-video-tests.ts | 8 ++ tsdef/types.d.ts | 3 + 31 files changed, 179 insertions(+), 127 deletions(-) rename lib/{createlocaltracks.js => createlocaltracks.ts} (60%) rename test/unit/spec/{createlocaltracks.js => createlocaltracks.ts} (95%) create mode 100644 tsdef/ConnectOptionsInternal.d.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index ad480bf1d..7ead1f2bb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -144,13 +144,6 @@ commands: name: Running Network Tests (environment = << pipeline.parameters.environment >>) command: scripts/circleci-run-tests.sh - save-test-results - framework-tests: - steps: - - build - - run: - name: Running Framework Tests - command: scripts/circleci-run-tests.sh - - save-test-results umd-tests: steps: - build @@ -237,12 +230,6 @@ jobs: TEST_STABILITY: << parameters.test_stability >> executor: machine-executor steps: [network-tests] - Framework-tests: - environment: - TEST_TYPE: "framework" - BROWSER: "chrome" - executor: docker-with-browser - steps: [framework-tests] UMD-tests: environment: BROWSER: "chrome" @@ -435,10 +422,6 @@ workflows: topology: ["group", "peer-to-peer"] test_stability: ["stable", "unstable"] requires: [Build, UnitTests] - - Framework-tests: - context: dockerhub-pulls - name: "framework tests" - requires: [Build, UnitTests] - UMD-tests: context: dockerhub-pulls name: "umd tests" diff --git a/CHANGELOG.md b/CHANGELOG.md index 748d5bb92..fc88c2b8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ The Twilio Programmable Video SDKs use [Semantic Versioning](http://www.semver.o **Version 1.x reached End of Life on September 8th, 2021.** See the changelog entry [here](https://www.twilio.com/changelog/end-of-life-complete-for-unsupported-versions-of-the-programmable-video-sdk). Support for the 1.x version ended on December 4th, 2020. +2.21.0 (March 8, 2022) +========================== + +New Features +------------ +- twilio-video.js now supports WKWebView and SFSafariViewController on iOS version 14.3 or later. The [`isSupported` flag](https://sdk.twilio.com/js/video/releases/2.20.1/docs/module-twilio-video.html) relies partly on the [User-Agent string](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) to determine if twilio-video.js officially supports the user's browser. If your application modifies the default value for the User-Agent string, the new value should follow the [correct format](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent#syntax). + + Additionally, for [iOS applications](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_ios), your application will need to include the [camera usage description](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/plist/info/NSCameraUsageDescription), [microphone usage description](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW25) and [inline media playback](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/1614793-allowsinlinemediaplayback) in order for the SDK to work on WKWebView. + + Note: As with Safari, WKWebViews only support only one local media track of each kind at a time. + + We also would like to thank @cbxp for his [contribution](https://github.com/twilio/twilio-webrtc.js/pull/133). (VIDEO-8374) + +Known Issue +----------- + +Some [common issues](https://github.com/twilio/twilio-video.js/blob/master/COMMON_ISSUES.md#safari-mobile) such as interruptions on mobile devices which includes, backgrounding the application, or switching between applications can sometimes cause VideoTracks to go black or AudioTracks to stop. + 2.20.1 (Feb 17, 2022) ===================== Bug Fixes diff --git a/README.md b/README.md index 39a42386a..af7ba0183 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,13 @@ View [CHANGELOG.md](https://github.com/twilio/twilio-video.js/blob/master/CHANGE Browser Support --------------- -| | Chrome | Edge (Chromium) | Firefox | Safari | -| ------------|--------|-----------------|---------|--------| -| **Android** | ✓ | - | ✓ | - | -| **iOS** | ✓ | - | * | ✓ | -| **Linux** | ✓ | - | ✓ | - | -| **macOS** | ✓ | ✓ ** | ✓ | ✓ | -| **Windows** | ✓ | ✓ ** | ✓ | - | +| | Chrome | Edge (Chromium) | Firefox | Safari | WebView | +| ------------|--------|-----------------|---------|--------|---------| +| **Android** | ✓ | - | ✓ | - | - | +| **iOS** | ✓ | - | * | ✓ | ✓ | +| **Linux** | ✓ | - | ✓ | - | - | +| **macOS** | ✓ | ✓ ** | ✓ | ✓ | - | +| **Windows** | ✓ | ✓ ** | ✓ | - | - | \*\* twilio-video.js supports the [Chromium-based Edge](https://www.microsoftedgeinsider.com/) browser. @@ -74,7 +74,7 @@ Releases of twilio-video.js are hosted on a CDN, and you can include these directly in your web app using a <script> tag. ```html - + ``` @@ -235,4 +235,3 @@ License ------- See [LICENSE.md](https://github.com/twilio/twilio-video.js/blob/master/LICENSE.md). - diff --git a/lib/connect.js b/lib/connect.js index 99b9622ef..7444244ce 100644 --- a/lib/connect.js +++ b/lib/connect.js @@ -3,7 +3,6 @@ const { MediaStreamTrack } = require('@twilio/webrtc'); const { guessBrowser, guessBrowserVersion } = require('@twilio/webrtc/lib/util'); const createCancelableRoomPromise = require('./cancelableroompromise'); -const createLocalTracks = require('./createlocaltracks'); const EncodingParametersImpl = require('./encodingparameters'); const LocalParticipant = require('./localparticipant'); const InsightsPublisher = require('./util/insightspublisher'); @@ -235,7 +234,6 @@ function connect(token, options) { options = Object.assign({ automaticSubscription: true, - createLocalTracks, dominantSpeaker: false, enableDscp: false, environment: DEFAULT_ENVIRONMENT, diff --git a/lib/createlocaltrack.js b/lib/createlocaltrack.js index 4cf0c43c3..e23aa6b4d 100644 --- a/lib/createlocaltrack.js +++ b/lib/createlocaltrack.js @@ -1,6 +1,5 @@ 'use strict'; -const defaultCreateLocalTracks = require('./createlocaltracks'); const { DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME } = require('./util/constants'); /** @@ -12,7 +11,6 @@ const { DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME } = require('./util/constants'); */ function createLocalTrack(kind, options) { options = Object.assign({ - createLocalTracks: defaultCreateLocalTracks, loggerName: DEFAULT_LOGGER_NAME, logLevel: DEFAULT_LOG_LEVEL, }, options); diff --git a/lib/createlocaltracks.js b/lib/createlocaltracks.ts similarity index 60% rename from lib/createlocaltracks.js rename to lib/createlocaltracks.ts index fcda77ac3..3b4dba6cd 100644 --- a/lib/createlocaltracks.js +++ b/lib/createlocaltracks.ts @@ -1,8 +1,9 @@ 'use strict'; -const asLocalTrack = require('./util').asLocalTrack; -const buildLogLevels = require('./util').buildLogLevels; -const getUserMedia = require('@twilio/webrtc').getUserMedia; +import { CreateLocalTrackOptions, CreateLocalTracksOptions, LocalTrack } from '../tsdef/types'; + +const { asLocalTrack, buildLogLevels } = require('./util'); +const { getUserMedia, MediaStreamTrack } = require('@twilio/webrtc'); const { LocalAudioTrack, @@ -10,7 +11,6 @@ const { LocalVideoTrack } = require('./media/track/es5'); -const MediaStreamTrack = require('@twilio/webrtc').MediaStreamTrack; const Log = require('./util/log'); const { DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME } = require('./util/constants'); const workaround180748 = require('./webaudio/workaround180748'); @@ -20,6 +20,19 @@ const workaround180748 = require('./webaudio/workaround180748'); // counter. let createLocalTrackCalls = 0; + +type ExtraLocalTrackOption = CreateLocalTrackOptions & { isCreatedByCreateLocalTracks?: boolean }; +type ExtraLocalTrackOptions = { audio: ExtraLocalTrackOption; video: ExtraLocalTrackOption; }; + +interface InternalOptions extends CreateLocalTracksOptions { + getUserMedia: any; + LocalAudioTrack: any; + LocalDataTrack: any; + LocalVideoTrack: any; + MediaStreamTrack: any; + Log: any; +}; + /** * Request {@link LocalTrack}s. By default, it requests a * {@link LocalAudioTrack} and a {@link LocalVideoTrack}. @@ -77,11 +90,11 @@ let createLocalTrackCalls = 0; * }); * */ -function createLocalTracks(options) { +export async function createLocalTracks(options?: CreateLocalTracksOptions): Promise { const isAudioVideoAbsent = !(options && ('audio' in options || 'video' in options)); - options = Object.assign({ + const fullOptions: InternalOptions = { audio: isAudioVideoAbsent, getUserMedia, loggerName: DEFAULT_LOGGER_NAME, @@ -91,80 +104,90 @@ function createLocalTracks(options) { LocalVideoTrack, MediaStreamTrack, Log, - video: isAudioVideoAbsent - }, options); + video: isAudioVideoAbsent, + ...options, + }; const logComponentName = `[createLocalTracks #${++createLocalTrackCalls}]`; - const logLevels = buildLogLevels(options.logLevel); - const log = new options.Log('default', logComponentName, logLevels, options.loggerName); + const logLevels = buildLogLevels(fullOptions.logLevel); + const log = new fullOptions.Log('default', logComponentName, logLevels, fullOptions.loggerName); + + const localTrackOptions = Object.assign({ log }, fullOptions); // NOTE(mmalavalli): The Room "name" in "options" was being used // as the LocalTrack name in asLocalTrack(). So we pass a copy of // "options" without the "name". - const localTrackOptions = Object.assign({ log }, options); - delete localTrackOptions.name; + // NOTE(joma): CreateLocalTracksOptions type does not really have a "name" property when used publicly by customers. + // But we are passing this property when used internally by other JS files. + // We can update this "any" type once those JS files are converted to TS. + delete (localTrackOptions as any).name; - if (options.audio === false && options.video === false) { + if (fullOptions.audio === false && fullOptions.video === false) { log.info('Neither audio nor video requested, so returning empty LocalTracks'); - return Promise.resolve([]); + return []; } - if (options.tracks) { + if (fullOptions.tracks) { log.info('Adding user-provided LocalTracks'); - log.debug('LocalTracks:', options.tracks); - return Promise.resolve(options.tracks); + log.debug('LocalTracks:', fullOptions.tracks); + return fullOptions.tracks; } - const extraLocalTrackOptions = { - audio: options.audio && options.audio.name - ? { name: options.audio.name } + const extraLocalTrackOptions: ExtraLocalTrackOptions = { + audio: typeof fullOptions.audio === 'object' && fullOptions.audio.name + ? { name: fullOptions.audio.name } : {}, - video: options.video && options.video.name - ? { name: options.video.name } + video: typeof fullOptions.video === 'object' && fullOptions.video.name + ? { name: fullOptions.video.name } : {} }; extraLocalTrackOptions.audio.isCreatedByCreateLocalTracks = true; extraLocalTrackOptions.video.isCreatedByCreateLocalTracks = true; - if (options.audio && typeof options.audio.workaroundWebKitBug1208516 === 'boolean') { - extraLocalTrackOptions.audio.workaroundWebKitBug1208516 = options.audio.workaroundWebKitBug1208516; + if (typeof fullOptions.audio === 'object' && typeof fullOptions.audio.workaroundWebKitBug1208516 === 'boolean') { + extraLocalTrackOptions.audio.workaroundWebKitBug1208516 = fullOptions.audio.workaroundWebKitBug1208516; } - if (options.video && typeof options.video.workaroundWebKitBug1208516 === 'boolean') { - extraLocalTrackOptions.video.workaroundWebKitBug1208516 = options.video.workaroundWebKitBug1208516; + if (typeof fullOptions.video === 'object' && typeof fullOptions.video.workaroundWebKitBug1208516 === 'boolean') { + extraLocalTrackOptions.video.workaroundWebKitBug1208516 = fullOptions.video.workaroundWebKitBug1208516; } - if (options.audio) { - delete options.audio.name; + if (typeof fullOptions.audio === 'object') { + delete fullOptions.audio.name; } - if (options.video) { - delete options.video.name; + if (typeof fullOptions.video === 'object') { + delete fullOptions.video.name; } const mediaStreamConstraints = { - audio: options.audio, - video: options.video + audio: fullOptions.audio, + video: fullOptions.video }; - const workaroundWebKitBug180748 = options.audio && options.audio.workaroundWebKitBug180748; + const workaroundWebKitBug180748 = typeof fullOptions.audio === 'object' && fullOptions.audio.workaroundWebKitBug180748; - const mediaStreamPromise = workaroundWebKitBug180748 - ? workaround180748(log, options.getUserMedia, mediaStreamConstraints) - : options.getUserMedia(mediaStreamConstraints); + try { + const mediaStream = await (workaroundWebKitBug180748 + ? workaround180748(log, fullOptions.getUserMedia, mediaStreamConstraints) + : fullOptions.getUserMedia(mediaStreamConstraints)); - return mediaStreamPromise.then(mediaStream => { - const mediaStreamTracks = mediaStream.getAudioTracks().concat(mediaStream.getVideoTracks()); + const mediaStreamTracks = [ + ...mediaStream.getAudioTracks(), + ...mediaStream.getVideoTracks(), + ]; log.info('Call to getUserMedia successful; got MediaStreamTracks:', mediaStreamTracks); - return mediaStreamTracks.map(mediaStreamTrack => asLocalTrack(mediaStreamTrack, Object.assign( - extraLocalTrackOptions[mediaStreamTrack.kind], localTrackOptions))); - }, error => { + return mediaStreamTracks.map(mediaStreamTrack => asLocalTrack(mediaStreamTrack, { + ...extraLocalTrackOptions[mediaStreamTrack.kind as 'audio' | 'video'], + ...localTrackOptions, + })); + } catch (error) { log.warn('Call to getUserMedia failed:', error); throw error; - }); + } } /** @@ -185,5 +208,3 @@ function createLocalTracks(options) { * get local video with getUserMedia when tracks * are not provided. */ - -module.exports = createLocalTracks; diff --git a/lib/index.ts b/lib/index.ts index 3206f42e7..2b2e52037 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,15 +1,15 @@ 'use strict'; -import type { ConnectOptions, CreateLocalTrackOptions, CreateLocalTracksOptions, LocalTrack } from '../tsdef/types'; +import type { ConnectOptions, CreateLocalTrackOptions } from '../tsdef/types'; import type { LocalAudioTrack as LocalAudioTrackType } from '../tsdef/LocalAudioTrack'; import type { LocalVideoTrack as LocalVideoTrackType } from '../tsdef/LocalVideoTrack'; import type { Log } from '../tsdef/loglevel'; import type { Room } from '../tsdef/Room'; +import { createLocalTracks } from './createlocaltracks'; import { runPreflight } from './preflight/preflighttest'; const internals = { connect: require('./connect'), createLocalAudioTrack: require('./createlocaltrack').audio, - createLocalTracks: require('./createlocaltracks'), createLocalVideoTrack: require('./createlocaltrack').video, isSupported: require('./util/support')(), version: require('../package.json').version, @@ -20,19 +20,27 @@ const internals = { }; function connect(token: string, options?: ConnectOptions): Promise { - return internals.connect(token, options); + const internalOptions = { + createLocalTracks, + ...options + }; + return internals.connect(token, internalOptions); } function createLocalAudioTrack(options?: CreateLocalTrackOptions): Promise { - return internals.createLocalAudioTrack(options); -} - -function createLocalTracks(options?: CreateLocalTracksOptions): Promise { - return internals.createLocalTracks(options); + const internalOptions = { + createLocalTracks, + ...options + }; + return internals.createLocalAudioTrack(internalOptions); } function createLocalVideoTrack(options?: CreateLocalTrackOptions): Promise { - return internals.createLocalVideoTrack(options); + const internalOptions = { + createLocalTracks, + ...options + }; + return internals.createLocalVideoTrack(internalOptions); } /** @@ -61,8 +69,8 @@ const LocalDataTrack = internals.LocalDataTrack; module.exports = { connect, createLocalAudioTrack, - createLocalTracks, createLocalVideoTrack, + createLocalTracks, runPreflight, isSupported, version, diff --git a/package.json b/package.json index a63b39ca6..8b9e1d160 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "twilio-video", "title": "Twilio Video", "description": "Twilio Video JavaScript Library", - "version": "2.20.2-dev", + "version": "2.21.0-dev", "homepage": "https://twilio.com", "author": "Mark Andrus Roberts ", "contributors": [ @@ -98,9 +98,7 @@ "lint:ts": "eslint ./tsdef/*.ts ./lib/**/*.ts", "lint": "npm-run-all lint:js lint:ts", "printVersion": "node --version && npm --version", - "test:unit": "npm-run-all printVersion build:es5 test:unit:js test:unit:ts", - "test:unit:js": "nyc --report-dir=./coverage/js --extension=.js --include=lib/**/* --reporter=html --reporter=lcov --reporter=text mocha ./test/unit/index.js", - "test:unit:ts": "nyc --report-dir=./coverage/ts --extension=.ts --include=lib/**/* --reporter=html --reporter=lcov --reporter=text mocha -r ts-node/register ./test/unit/index.ts", + "test:unit": "npm-run-all printVersion build:es5 && nyc --report-dir=./coverage --include=lib/**/* --reporter=html --reporter=lcov --reporter=text mocha -r ts-node/register ./test/unit/*", "test:serversiderender": "mocha ./test/serversiderender/index.js", "test:integration:adapter": "node ./scripts/karma.js karma/integration.adapter.conf.js", "test:integration": "npm run build:es5 && node ./scripts/karma.js karma/integration.conf.js", @@ -146,7 +144,7 @@ "clean": "rimraf ./coverage ./es5 ./dist" }, "dependencies": { - "@twilio/webrtc": "4.5.2", + "@twilio/webrtc": "4.6.0", "backoff": "^2.5.0", "ws": "^7.4.6", "xmlhttprequest": "^1.8.0" diff --git a/scripts/docs.js b/scripts/docs.js index f19a9bd08..324ec5bf4 100755 --- a/scripts/docs.js +++ b/scripts/docs.js @@ -12,7 +12,6 @@ const docs = process.argv[2]; const publicClasses = [ 'lib/connect.js', 'lib/createlocaltrack.js', - 'lib/createlocaltracks.js', 'lib/room.js', 'lib/media/track/index.js', 'lib/media/track/audiotrack.js', @@ -57,6 +56,7 @@ const publicClasses = [ 'lib/util/twilioerror.js', // TS Files + 'lib/createlocaltracks.ts', 'lib/index.ts', 'lib/preflight/preflighttest.ts', ]; diff --git a/test/integration/index.js b/test/integration/index.js index d9b15e467..4935dbb37 100644 --- a/test/integration/index.js +++ b/test/integration/index.js @@ -2,7 +2,7 @@ require('./spec/browserbugs/chromium'); require('./spec/docker/reconnection'); require('./spec/docker/docker'); -require('./spec/bandwidthprofile/publisheerhints.js'); +require('./spec/bandwidthprofile/publisherhints.js'); require('./spec/bandwidthprofile/regressions'); require('./spec/bandwidthprofile/renderhints'); require('./spec/bandwidthprofile/video'); diff --git a/test/integration/spec/audioonlyrooms.js b/test/integration/spec/audioonlyrooms.js index d98c45ef3..b52342db4 100644 --- a/test/integration/spec/audioonlyrooms.js +++ b/test/integration/spec/audioonlyrooms.js @@ -2,7 +2,7 @@ const assert = require('assert'); -const createLocalTracks = require('../../../es5/createlocaltracks'); +const createLocalTracks = require('../../../es5/index').createLocalTracks; const { RoomTrackKindNotSupportedError } = require('../../../es5/util/twilio-video-errors'); const LocalDataTrack = require('../../../es5/media/track/es5/localdatatrack'); const LocalTrackPublication = require('../../../es5/media/track/localtrackpublication'); diff --git a/test/integration/spec/bandwidthprofile/publisherhints.js b/test/integration/spec/bandwidthprofile/publisherhints.js index 73de7343a..591c7e266 100644 --- a/test/integration/spec/bandwidthprofile/publisherhints.js +++ b/test/integration/spec/bandwidthprofile/publisherhints.js @@ -3,10 +3,8 @@ 'use strict'; const assert = require('assert'); -const { video: createLocalVideoTrack, audio: createLocalAudioTrack } = require('../../../../es5/createlocaltrack'); const defaults = require('../../../lib/defaults'); -const { Logger } = require('../../../../es5'); -const connect = require('../../../../es5/connect'); +const { Logger, connect, createLocalAudioTrack, createLocalVideoTrack } = require('../../../../es5'); const { createRoom, completeRoom } = require('../../../lib/rest'); const getToken = require('../../../lib/token'); const { isFirefox } = require('../../../lib/guessbrowser'); diff --git a/test/integration/spec/bandwidthprofile/regressions.js b/test/integration/spec/bandwidthprofile/regressions.js index 5878e4ced..67933b9f7 100644 --- a/test/integration/spec/bandwidthprofile/regressions.js +++ b/test/integration/spec/bandwidthprofile/regressions.js @@ -3,10 +3,9 @@ 'use strict'; const assert = require('assert'); -const { audio: createLocalAudioTrack, video: createLocalVideoTrack } = require('../../../../es5/createlocaltrack'); const defaults = require('../../../lib/defaults'); const { completeRoom } = require('../../../lib/rest'); -const { Logger } = require('../../../../es5'); +const { createLocalAudioTrack, createLocalVideoTrack, Logger } = require('../../../../es5'); const { createSyntheticAudioStreamTrack, @@ -115,4 +114,3 @@ describe('BandwidthProfileOptions: regressions', function() { }); }); }); - diff --git a/test/integration/spec/bandwidthprofile/renderhints.js b/test/integration/spec/bandwidthprofile/renderhints.js index 25751a915..3d3229b6a 100644 --- a/test/integration/spec/bandwidthprofile/renderhints.js +++ b/test/integration/spec/bandwidthprofile/renderhints.js @@ -3,9 +3,8 @@ 'use strict'; const assert = require('assert'); -const { video: createLocalVideoTrack } = require('../../../../es5/createlocaltrack'); const defaults = require('../../../lib/defaults'); -const { Logger } = require('../../../../es5'); +const { Logger, createLocalVideoTrack } = require('../../../../es5'); const { tracksSubscribed, @@ -382,4 +381,3 @@ describe('BandwidthProfileOptions: renderHints', function() { }); }); }); - diff --git a/test/integration/spec/bandwidthprofile/video.js b/test/integration/spec/bandwidthprofile/video.js index 07b4ccbf8..57ca15aeb 100644 --- a/test/integration/spec/bandwidthprofile/video.js +++ b/test/integration/spec/bandwidthprofile/video.js @@ -3,12 +3,10 @@ 'use strict'; const assert = require('assert'); -const connect = require('../../../../es5/connect'); -const { audio: createLocalAudioTrack, video: createLocalVideoTrack } = require('../../../../es5/createlocaltrack'); +const { Logger, connect, createLocalAudioTrack, createLocalVideoTrack } = require('../../../../es5'); const defaults = require('../../../lib/defaults'); const { createRoom, completeRoom } = require('../../../lib/rest'); const getToken = require('../../../lib/token'); -const { Logger } = require('../../../../es5'); const { capitalize, @@ -193,4 +191,3 @@ describe('BandwidthProfileOptions: video', function() { }); }); }); - diff --git a/test/integration/spec/connect.js b/test/integration/spec/connect.js index 0444a1b9c..f583d169c 100644 --- a/test/integration/spec/connect.js +++ b/test/integration/spec/connect.js @@ -6,9 +6,7 @@ const { EventEmitter } = require('events'); const { getUserMedia } = require('@twilio/webrtc'); const sinon = require('sinon'); -const connect = require('../../../es5/connect'); -const { audio: createLocalAudioTrack, video: createLocalVideoTrack } = require('../../../es5/createlocaltrack'); -const createLocalTracks = require('../../../es5/createlocaltracks'); +const { connect, createLocalTracks, createLocalAudioTrack, createLocalVideoTrack } = require('../../../es5'); const LocalDataTrack = require('../../../es5/media/track/es5/localdatatrack'); const Room = require('../../../es5/room'); const { flatMap } = require('../../../es5/util'); diff --git a/test/integration/spec/leaktests.js b/test/integration/spec/leaktests.js index ad3a8274b..ff3025816 100644 --- a/test/integration/spec/leaktests.js +++ b/test/integration/spec/leaktests.js @@ -4,8 +4,7 @@ const assert = require('assert'); const defaults = require('../../lib/defaults'); const { completeRoom, createRoom } = require('../../lib/rest'); -const { audio: createLocalAudioTrack, video: createLocalVideoTrack } = require('../../../lib/createlocaltrack'); -const connect = require('../../../lib/connect'); +const { connect, createLocalAudioTrack, createLocalVideoTrack } = require('../../../es5'); const getToken = require('../../lib/token'); const { isChrome } = require('../../lib/guessbrowser'); diff --git a/test/integration/spec/localtracks.js b/test/integration/spec/localtracks.js index 3f22eb449..a9ca8ba5e 100644 --- a/test/integration/spec/localtracks.js +++ b/test/integration/spec/localtracks.js @@ -17,11 +17,10 @@ const { waitForSometime } = require('../../lib/util'); -const createLocalTracks = require('../../../es5/createlocaltrack'); -const connect = require('../../../es5/connect'); +const { connect, createLocalAudioTrack, createLocalVideoTrack } = require('../../../es5'); ['audio', 'video'].forEach(kind => { - const createLocalTrack = createLocalTracks[kind]; + const createLocalTrack = kind === 'audio' ? createLocalAudioTrack : createLocalVideoTrack; const description = 'Local' + kind[0].toUpperCase() + kind.slice(1) + 'Track'; const options = { diff --git a/test/integration/spec/logger.js b/test/integration/spec/logger.js index 9b4e0928a..c3e3cd3e0 100644 --- a/test/integration/spec/logger.js +++ b/test/integration/spec/logger.js @@ -6,7 +6,7 @@ const sinon = require('sinon'); const { Logger } = require('../../../es5'); const defaults = require('../../lib/defaults'); -const defaultConnect = require('../../../es5/connect'); +const defaultConnect = require('../../../es5').connect; const getToken = require('../../lib/token'); const { createRoom, completeRoom } = require('../../lib/rest'); const { randomName } = require('../../lib/util'); diff --git a/test/integration/spec/remotetracks.js b/test/integration/spec/remotetracks.js index a16f6cd2d..52746a0f5 100644 --- a/test/integration/spec/remotetracks.js +++ b/test/integration/spec/remotetracks.js @@ -6,8 +6,7 @@ const { trackPriority } = require('../../../es5/util/constants'); const LocalDataTrack = require('../../../es5/media/track/es5/localdatatrack'); const defaults = require('../../lib/defaults'); const { completeRoom, createRoom } = require('../../lib/rest'); -const { audio: createLocalAudioTrack, video: createLocalVideoTrack } = require('../../../es5/createlocaltrack'); -const connect = require('../../../es5/connect'); +const { connect, createLocalAudioTrack, createLocalVideoTrack } = require('../../../es5'); const getToken = require('../../lib/token'); const { isFirefox } = require('../../lib/guessbrowser'); diff --git a/test/integration/spec/rest.js b/test/integration/spec/rest.js index c47b269fa..c9f45d6a9 100644 --- a/test/integration/spec/rest.js +++ b/test/integration/spec/rest.js @@ -23,7 +23,7 @@ const { unsubscribeTrack } = require('../../lib/rest'); -const connect = require('../../../es5/connect'); +const { connect } = require('../../../es5'); const { RoomMaxParticipantsExceededError } = require('../../../es5/util/twilio-video-errors'); describe('REST APIs', function() { diff --git a/test/integration/spec/room.js b/test/integration/spec/room.js index 19a237fa8..c0d9f94b1 100644 --- a/test/integration/spec/room.js +++ b/test/integration/spec/room.js @@ -6,6 +6,8 @@ const assert = require('assert'); const { connect, createLocalTracks, + createLocalAudioTrack, + createLocalVideoTrack, LocalDataTrack } = require('../../../es5'); @@ -15,7 +17,6 @@ const { } = require('../../../es5/util/twilio-video-errors'); const { isChrome, isSafari } = require('../../lib/guessbrowser'); -const { audio: createLocalAudioTrack, video: createLocalVideoTrack } = require('../../../es5/createlocaltrack'); const RemoteParticipant = require('../../../es5/remoteparticipant'); const { flatMap, smallVideoConstraints } = require('../../../es5/util'); diff --git a/test/lib/util.js b/test/lib/util.js index 4600ac51c..e637f658f 100644 --- a/test/lib/util.js +++ b/test/lib/util.js @@ -12,7 +12,7 @@ const defaults = require('../lib/defaults'); const getToken = require('../lib/token'); const { ecs } = require('../lib/post'); const { createRoom } = require('../lib/rest'); -const connect = require('../../es5/connect'); +const { connect } = require('../../es5'); const second = 1000; const assert = require('assert'); diff --git a/test/unit/index.js b/test/unit/index.js index 0de8be54d..6d528e378 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -6,7 +6,6 @@ if (typeof window === 'undefined') { require('./spec/connect'); require('./spec/createlocaltrack'); -require('./spec/createlocaltracks'); require('./spec/encodingparameters'); require('./spec/localparticipant'); require('./spec/networkqualityconfiguration'); diff --git a/test/unit/index.ts b/test/unit/index.ts index 80f958c65..49c1f8830 100644 --- a/test/unit/index.ts +++ b/test/unit/index.ts @@ -1,3 +1,4 @@ +import './spec/createlocaltracks'; +import './spec/mos'; import './spec/preflight'; import './spec/timer'; -import './spec/mos'; diff --git a/test/unit/spec/connect.js b/test/unit/spec/connect.js index 47e73b29d..9797aacb2 100644 --- a/test/unit/spec/connect.js +++ b/test/unit/spec/connect.js @@ -504,6 +504,10 @@ describe('connect', () => { it('does not set shouldStopLocalTracks on the LocalParticipant', async () => { const stream = await fakeGetUserMedia({ audio: true, video: true }); const tracks = stream.getTracks().map(track => new FakeLocalTrack(track)); + // eslint-disable-next-line require-await + async function createLocalTracks() { + return tracks; + } const mockSignaling = new Signaling(); mockSignaling.connect = () => Promise.resolve(() => new RoomSignaling()); @@ -517,6 +521,7 @@ describe('connect', () => { } await connect(token, { + createLocalTracks, LocalAudioTrack: FakeLocalTrack, LocalParticipant, LocalVideoTrack: FakeLocalTrack, diff --git a/test/unit/spec/createlocaltracks.js b/test/unit/spec/createlocaltracks.ts similarity index 95% rename from test/unit/spec/createlocaltracks.js rename to test/unit/spec/createlocaltracks.ts index 1bfe7a435..46d4fb767 100644 --- a/test/unit/spec/createlocaltracks.js +++ b/test/unit/spec/createlocaltracks.ts @@ -1,11 +1,9 @@ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); - -const createLocalTracks = require('../../../lib/createlocaltracks'); - -const { FakeMediaStreamTrack, fakeGetUserMedia } = require('../../lib/fakemediastream'); +import * as assert from 'assert'; +import * as sinon from 'sinon'; +import { createLocalTracks } from '../../../lib/createlocaltracks'; +import { fakeGetUserMedia, FakeMediaStreamTrack } from '../../lib/fakemediastream'; describe('createLocalTracks', () => { [ diff --git a/test/unit/spec/util/support.js b/test/unit/spec/util/support.js index 493696406..be3e152a0 100644 --- a/test/unit/spec/util/support.js +++ b/test/unit/spec/util/support.js @@ -81,6 +81,29 @@ describe('isSupported', () => { 'Safari on Mac', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13 Safari/605.1.15' ], + [ + 'Safari WKWebView - iPhone', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)', + ], + [ + 'Safari WKWebView - iPad', + 'Mozilla/5.0 (iPad; CPU OS 15_3 like Mac OS X) AppleWebkit/605.1.15 (KHTML, like Gecko) Mobile/15E148', + ], + [ + 'Safari iOS - Instagram', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Instagram 220.0.0.8.117 (iPhone12,3; iOS 15_3; en_US; en; scale=3.00; 1125x2436; 347566818) NW/3', + 'safari' + ], + [ + 'Safari iOS - Snapchat', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Snapchat/11.64.0.38 (like Safari/8612.4.9.0.3, panda)', + 'safari' + ], + [ + 'Safari iOS - Slack ', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1', + 'safari' + ], [ 'Edge (Chromium) on Mac', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66', diff --git a/tsdef/ConnectOptionsInternal.d.ts b/tsdef/ConnectOptionsInternal.d.ts new file mode 100644 index 000000000..a13dd92d0 --- /dev/null +++ b/tsdef/ConnectOptionsInternal.d.ts @@ -0,0 +1,5 @@ +import { ConnectOptions } from './types'; + +export interface ConnectOptionsInternal extends ConnectOptions { + createLocalTracks?: any; +} diff --git a/tsdef/twilio-video-tests.ts b/tsdef/twilio-video-tests.ts index 418bd4548..f09be8452 100644 --- a/tsdef/twilio-video-tests.ts +++ b/tsdef/twilio-video-tests.ts @@ -229,6 +229,7 @@ function LocalParticipant(localParticipant: Video.LocalParticipant) { let room: Video.Room | null = null; let localVideoTrack: Video.LocalVideoTrack | null = null; let localAudioTrack: Video.LocalAudioTrack | null = null; +let localTracks: Video.LocalTrack[] | null = null; // Testing finally method const maybeRoom = Video.connect('$TOKEN', { @@ -293,6 +294,13 @@ async function initRoom() { room.localParticipant.publishTrack(localAudioTrack); room.participants.forEach(participantConnected); + localTracks = await Video.createLocalTracks({ audio: true, video: false }); + await Video.createLocalTracks({ audio: true }); + await Video.connect('$TOKEN', { + name: 'my-cool-room', + tracks: localTracks + }); + room.on('participantConnected', participantConnected); room.on('participantDisconnected', participantDisconnected); room.once('disconnected', (room: Video.Room, error: Video.TwilioError) => { diff --git a/tsdef/types.d.ts b/tsdef/types.d.ts index 4595db98d..4f2e8bd15 100644 --- a/tsdef/types.d.ts +++ b/tsdef/types.d.ts @@ -161,6 +161,7 @@ export interface CreateLocalTrackOptions extends MediaTrackConstraints { logLevel?: LogLevel | LogLevels; name?: string; workaroundWebKitBug180748?: boolean; + workaroundWebKitBug1208516?: boolean; } export interface ConnectOptions { @@ -206,6 +207,8 @@ export interface CreateLocalTracksOptions { * @deprecated */ logLevel?: LogLevel | LogLevels; + loggerName?: string; + tracks?: LocalTrack[]; video?: boolean | CreateLocalTrackOptions; }