From 3e87bac0a2321b8db988355d4573a8bc81afed28 Mon Sep 17 00:00:00 2001 From: vmalviya Date: Fri, 25 Feb 2022 11:59:17 -0800 Subject: [PATCH] feat: enhance browser support (#59) * feat: adding support for all supported browsers and platforms * fix: missing browser version * fix: trying different concurrency * fix: comment out chrome tests * fix: trying sauce reconnect option * fix: adding chrome tests back * fix: adding test for video constraints * fix: test case fix for error scenario * fix: remove extra constraints --- ci/Jenkinsfile | 34 ++++- cspell.json | 10 +- karma.conf.js | 271 ++++++++++++++++++++++++++-------- package.json | 5 +- src/media.integration-test.ts | 12 ++ 5 files changed, 264 insertions(+), 68 deletions(-) diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile index d67c53e..9d196ee 100644 --- a/ci/Jenkinsfile +++ b/ci/Jenkinsfile @@ -52,13 +52,43 @@ pipeline { sourceFileResolver: sourceFiles('NEVER_STORE') } } - stage('Run Integration Test') { + stage('Run Integration Tests on Chrome') { steps { withCredentials([string(credentialsId: 'SAUCE_ACCESS_KEY', variable: 'SAUCE_ACCESS_KEY')]) { echo "SAUCE=$SAUCE" echo "SAUCE_USERNAME=$SAUCE_USERNAME" echo "SAUCE_ACCESS_KEY=$SAUCE_ACCESS_KEY" - sh './node_modules/yarn/bin/yarn test:integration' + sh './node_modules/yarn/bin/yarn test:integration:chrome' + } + } + } + stage('Run Integration Tests on Safari') { + steps { + withCredentials([string(credentialsId: 'SAUCE_ACCESS_KEY', variable: 'SAUCE_ACCESS_KEY')]) { + echo "SAUCE=$SAUCE" + echo "SAUCE_USERNAME=$SAUCE_USERNAME" + echo "SAUCE_ACCESS_KEY=$SAUCE_ACCESS_KEY" + sh './node_modules/yarn/bin/yarn test:integration:safari' + } + } + } + stage('Run Integration Tests on Firefox') { + steps { + withCredentials([string(credentialsId: 'SAUCE_ACCESS_KEY', variable: 'SAUCE_ACCESS_KEY')]) { + echo "SAUCE=$SAUCE" + echo "SAUCE_USERNAME=$SAUCE_USERNAME" + echo "SAUCE_ACCESS_KEY=$SAUCE_ACCESS_KEY" + sh './node_modules/yarn/bin/yarn test:integration:firefox' + } + } + } + stage('Run Integration Tests on Edge') { + steps { + withCredentials([string(credentialsId: 'SAUCE_ACCESS_KEY', variable: 'SAUCE_ACCESS_KEY')]) { + echo "SAUCE=$SAUCE" + echo "SAUCE_USERNAME=$SAUCE_USERNAME" + echo "SAUCE_ACCESS_KEY=$SAUCE_ACCESS_KEY" + sh './node_modules/yarn/bin/yarn test:integration:edge' } } } diff --git a/cspell.json b/cspell.json index 486110e..089aed0 100644 --- a/cspell.json +++ b/cspell.json @@ -4,8 +4,8 @@ "language": "en", "words": [ "Alboe", - "bitjson", "bitauth", + "bitjson", "cimg", "circleci", "codecov", @@ -23,14 +23,16 @@ "gohri", "libauth", "mkdir", - "rohit", + "negotiatedneeded", + "preprocessors", "prettierignore", + "rohit", "sandboxed", + "saucelabs", "transpiled", "typedoc", "untracked", - "webrtc", - "negotiatedneeded" + "webrtc" ], "flagWords": [], "ignorePaths": [ diff --git a/karma.conf.js b/karma.conf.js index d2ab2d5..20cc7c3 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -24,6 +24,8 @@ module.exports = (config) => { screenResolution: '1600x1200', extendedDebugging: true, capturePerformance: true, + connectRetries: 2, + connectRetryTimeout: 2000, }; const firefoxOptions = { @@ -47,6 +49,7 @@ module.exports = (config) => { 'ignore-gpu-blacklist', 'test-type', 'disable-gpu', + '--no-sandbox', '--disable-features=WebRtcHideLocalIpsWithMdns', '--use-fake-device-for-media-stream', '--use-fake-ui-for-media-stream', @@ -56,6 +59,193 @@ module.exports = (config) => { ], }; + const chromeSauceOptions = { + base: 'SauceLabs', + browserName: 'chrome', + 'goog:chromeOptions': chromeOptions, + 'sauce:options': { + ...sharedSauceOptions, + tags: ['w3c-chrome'], + }, + }; + + /** + * Utility method to create config object of all supported chrome versions on all supported platforms. + * + * @returns Sauce lab config object for chrome browser. + */ + const getChromeLaunchers = () => { + const chromeVersions = [ + '80', + '81', + '83', + '84', + '85', + '86', + '87', + '88', + '89', + '90', + '91', + '92', + '93', + '94', + '95', + '96', + '97', + ]; + const platforms = ['Windows 10', 'macOS 11', 'macOS 12']; + const chromeLaunchers = {}; + platforms.forEach((platform) => { + chromeVersions.forEach((version) => { + chromeLaunchers[`chrome_${version}_${platform}`] = { + ...chromeSauceOptions, + browserVersion: version, + platformName: platform, + }; + }); + }); + return chromeLaunchers; + }; + + const firefoxSauceOptions = { + base: 'SauceLabs', + browserName: 'firefox', + 'moz:firefoxOptions': firefoxOptions, + 'sauce:options': { + ...sharedSauceOptions, + tags: ['w3c-firefox'], + }, + }; + + /** + * Utility method to create config object of all supported firefox versions on all supported platforms. + * + * @returns Sauce lab config object for firefox browser. + */ + const getFirefoxLaunchers = () => { + const firefoxVersions = [ + '70', + '71', + '72', + '73', + '74', + '75', + '76', + '77', + '78', + '79', + '80', + '81', + '82', + '83', + '84', + '85', + '86', + '87', + '88', + '89', + '90', + '91', + '92', + '93', + '94', + '95', + '96', + ]; + const platforms = ['Windows 10', 'Windows 11', 'macOS 11', 'macOS 12']; + const firefoxLaunchers = {}; + platforms.forEach((platform) => { + firefoxVersions.forEach((version) => { + firefoxLaunchers[`firefox_${version}_${platform}`] = { + ...firefoxSauceOptions, + browserVersion: version, + platformName: platform, + }; + }); + }); + return firefoxLaunchers; + }; + + const safariSauceOptions = { + base: 'SauceLabs', + browserName: 'Safari', + 'sauce:options': { + ...sharedSauceOptions, + tags: ['w3c-safari'], + }, + }; + + /** + * Utility method to create config object of all supported safari versions on all supported platforms. + * + * @returns Sauce lab config object for safari browser. + */ + const getSafariLaunchers = () => { + const safariLaunchers = { + 'safari_14_macOS 11': { + ...safariSauceOptions, + browserVersion: '14', + platformName: 'macOS 11', + }, + 'safari_15_macOS 12': { + ...safariSauceOptions, + browserVersion: '15', + platformName: 'macOS 12', + }, + }; + return safariLaunchers; + }; + + const edgeSauceOptions = { + base: 'SauceLabs', + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': chromeOptions, + 'sauce:options': { + ...sharedSauceOptions, + tags: ['w3c-edge'], + }, + }; + + /** + * Utility method to create config object of all supported edge versions on all supported platforms. + * + * @returns Sauce lab config object for edge browser. + */ + const getEdgeLaunchers = () => { + const edgeVersions = [ + '80', + '81', + '83', + '84', + '85', + '86', + '87', + '88', + '89', + '90', + '91', + '92', + '93', + '94', + '95', + '96', + '97', + ]; + const platforms = ['Windows 10', 'Windows 11']; + const edgeLaunchers = {}; + platforms.forEach((platform) => { + edgeVersions.forEach((version) => { + edgeLaunchers[`edge_${version}_${platform}`] = { + ...edgeSauceOptions, + browserVersion: version, + platformName: platform, + }; + }); + }); + return edgeLaunchers; + }; + const localLaunchers = { chrome: { base: 'ChromeHeadless', @@ -80,64 +270,10 @@ module.exports = (config) => { }, }; - const sauceLaunchers = { - sl_chrome_mac11: { - base: 'SauceLabs', - browserName: 'chrome', - browserVersion: 'latest', - platformName: 'macOS 11', - 'goog:chromeOptions': chromeOptions, - 'sauce:options': { - ...sharedSauceOptions, - tags: ['w3c-chrome'], - }, - }, - sl_chrome_win10: { - base: 'SauceLabs', - browserName: 'chrome', - browserVersion: 'latest', - platformName: 'Windows 10', - 'goog:chromeOptions': chromeOptions, - 'sauce:options': { - ...sharedSauceOptions, - tags: ['w3c-chrome'], - }, - }, - sl_safari_mac11: { - base: 'SauceLabs', - browserName: 'Safari', - browserVersion: 'latest', - platformName: 'macOS 11', - 'sauce:options': { - ...sharedSauceOptions, - tags: ['w3c-safari'], - }, - }, - sl_firefox_mac11: { - base: 'SauceLabs', - browserName: 'firefox', - browserVersion: 'latest', - platformName: 'macOS 11', - 'moz:firefoxOptions': firefoxOptions, - 'sauce:options': { - ...sharedSauceOptions, - tags: ['w3c-firefox'], - }, - }, - sl_firefox_win10: { - base: 'SauceLabs', - browserName: 'firefox', - browserVersion: 'latest', - platformName: 'Windows 10', - 'moz:firefoxOptions': firefoxOptions, - 'sauce:options': { - ...sharedSauceOptions, - tags: ['w3c-firefox'], - }, - }, - }; - - const customLaunchers = { ...localLaunchers, ...sauceLaunchers }; + const chromeLaunchers = getChromeLaunchers(); + const firefoxLaunchers = getFirefoxLaunchers(); + const safariLaunchers = getSafariLaunchers(); + const edgeLaunchers = getEdgeLaunchers(); if (useSauceConnect && !SAUCE_USERNAME && !SAUCE_ACCESS_KEY) { // eslint-disable-next-line no-console @@ -159,12 +295,10 @@ module.exports = (config) => { port: 9876, logLevel: config.DEBUG, autoWatch: false, - customLaunchers, - browsers: useSauceConnect ? Object.keys(sauceLaunchers) : browsers, singleRun: true, concurrency: Infinity, timeout, - captureTimeout: 120000, + captureTimeout: 240000, karmaTypescriptConfig: { tsconfig: './tsconfig.json', compilerOptions: { @@ -211,5 +345,20 @@ module.exports = (config) => { }, }; + let sauceLaunchers = {}; + if (useSauceConnect) { + if (config.chrome) { + sauceLaunchers = { ...chromeLaunchers }; + } else if (config.firefox) { + sauceLaunchers = { ...firefoxLaunchers }; + } else if (config.edge) { + sauceLaunchers = { ...edgeLaunchers }; + } else if (config.safari) { + sauceLaunchers = { ...safariLaunchers }; + } + } + karmaConfig.customLaunchers = { ...localLaunchers, ...sauceLaunchers }; + karmaConfig.browsers = useSauceConnect ? Object.keys(sauceLaunchers) : browsers; + config.set(karmaConfig); }; diff --git a/package.json b/package.json index 1ca7162..ebf1431 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,10 @@ "test:spelling": "cspell \"{README.md,.github/*.md,src/**/*.ts}\"", "test:unit": "jest", "test:coverage": "jest --coverage", - "test:integration": "karma start --integration", + "test:integration:safari": "karma start --integration --safari", + "test:integration:chrome": "karma start --integration --chrome", + "test:integration:firefox": "karma start --integration --firefox", + "test:integration:edge": "karma start --integration --edge", "transpile": "tsc", "transpile:clean": "rimraf ./dist", "transpile:validate": "tsc --noemit", diff --git a/src/media.integration-test.ts b/src/media.integration-test.ts index 8534998..929b79f 100644 --- a/src/media.integration-test.ts +++ b/src/media.integration-test.ts @@ -9,6 +9,18 @@ describe('Media integration test', () => { const cameraStream: MediaStream = await getUserMedia({ video: true }); expect(cameraStream.getTracks()[0].kind).equal('video'); }); + + it('should return a video stream with constraints', async () => { + const cameraStream = await getUserMedia({ + video: { + aspectRatio: 1.777, + width: 1920, + height: 1080, + frameRate: 30, + }, + }); + expect(cameraStream.getTracks()[0].kind).equal('video'); + }); }); describe('getUserMedia audio', () => {