Skip to content

Commit

Permalink
Feat: initial integration tests (#55)
Browse files Browse the repository at this point in the history
* feat: add initial integration tests for media

* fix: update version

* fix: minor update

* fix: address code review comments

* fix: revert version update

* fix: test jenkins builds using personal credentials

* fix: add missing bracket

* fix: exclude tests files from sonar

* fix: use sauce credentials from env variables

* fix: update script to read sauce access key from secret credentials

* fix: update script to display variable names
  • Loading branch information
vibhaMalviya authored and GitHub Enterprise committed Dec 2, 2021
1 parent d265cdc commit a1de883
Show file tree
Hide file tree
Showing 6 changed files with 4,322 additions and 113 deletions.
10 changes: 10 additions & 0 deletions ci/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ pipeline {
sourceFileResolver: sourceFiles('NEVER_STORE')
}
}
stage('Run Integration Test') {
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'
}
}
}
stage('SonarQube Analysis') {
environment {
scannerHome = tool 'sonar-scanner'
Expand Down
215 changes: 215 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// eslint-disable-next-line
const typescriptTransform = require('karma-typescript-es6-transform');
// eslint-disable-next-line
process.env.CHROME_BIN = require('puppeteer').executablePath();

/**
* Karma runner configuration.
*
* @param config - Karma configuration.
*/
module.exports = (config) => {
const { SAUCE, SAUCE_USERNAME, SAUCE_ACCESS_KEY, TEST_TIMEOUT, BUILD_NUMBER, NODE_ENV } =
process.env;

const browsers = ['chrome'];
const appName = 'webrtc-core';
const environment = NODE_ENV || 'dev';
const buildNumber = BUILD_NUMBER || new Date().toUTCString();
const buildName = `${appName}-tests-${environment}#${buildNumber}`;
const useSauceConnect = SAUCE === 'true';
const timeout = TEST_TIMEOUT || 60000;

const sharedSauceOptions = {
screenResolution: '1600x1200',
extendedDebugging: true,
capturePerformance: true,
};

const firefoxOptions = {
prefs: {
'devtools.chrome.enabled': true,
'devtools.debugger.prompt-connection': false,
'devtools.debugger.remote-enabled': true,
'dom.webnotifications.enabled': false,
'media.navigator.streams.fake': true,
'media.getusermedia.screensharing.enabled': true,
'media.navigator.permission.disabled': true,
'media.getusermedia.video.enabled': true,
'media.getusermedia.audio.enabled': true,
},
};

const chromeOptions = {
args: [
'start-maximized',
'disable-infobars',
'ignore-gpu-blacklist',
'test-type',
'disable-gpu',
'--disable-features=WebRtcHideLocalIpsWithMdns',
'--use-fake-device-for-media-stream',
'--use-fake-ui-for-media-stream',
'--enable-experimental-web-platform-features',
'--allow-insecure-localhost',
'--unsafely-treat-insecure-origin-as-secure',
],
};

const localLaunchers = {
chrome: {
base: 'ChromeHeadless',
flags: [
'--no-sandbox',
'--disable-web-security',
'--use-fake-device-for-media-stream',
'--use-fake-ui-for-media-stream',
],
},
firefox: {
base: 'Firefox',
flags: firefoxOptions.prefs,
},
safari: {
base: 'Safari',
flags: {
'webkit:WebRTC': {
DisableInsecureMediaCapture: true,
},
},
},
};

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 };

if (useSauceConnect && !SAUCE_USERNAME && !SAUCE_ACCESS_KEY) {
// eslint-disable-next-line no-console
console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.');
process.exit(1);
}

const files = ['src/**/*.ts'];

const karmaConfig = {
basePath: '.',
frameworks: ['mocha', 'chai', 'karma-typescript'],
files,
preprocessors: {
'src/**/*.ts': ['karma-typescript'],
},
exclude: [],
reporters: ['junit', 'karma-typescript', 'saucelabs', 'mocha', 'coverage'],
port: 9876,
logLevel: config.DEBUG,
autoWatch: false,
customLaunchers,
browsers: useSauceConnect ? Object.keys(sauceLaunchers) : browsers,
singleRun: true,
concurrency: Infinity,
timeout,
captureTimeout: 120000,
karmaTypescriptConfig: {
tsconfig: './tsconfig.json',
compilerOptions: {
allowJs: true,
module: 'commonjs',
resolveJsonModule: false,
},
bundlerOptions: {
debug: true,
addNodeGlobals: false,
entrypoints: config.integration ? /\.integration-test\.ts/i : /\.test\.ts$/i,
transforms: [typescriptTransform()],
},
coverageOptions: {
exclude: [/\.(d|spec|test)\.ts$/i],
},
},
sauceLabs: {
build: buildName,
recordScreenshots: true,
recordVideo: true,
tags: ['web-rtc-core'],
testName: `${config.integration ? 'Integration Tests' : 'Unit Tests'}`,
connectOptions: {
logfile: './sauce.log',
noSslBumpDomains: [
'idbroker.webex.com',
'idbrokerbts.webex.com',
'127.0.0.1',
'localhost',
'*.wbx2.com',
'*.ciscospark.com',
],
tunnelDomains: ['127.0.0.1', 'localhost'],
},
},
coverageReporter: {
type: 'html',
dir: 'coverage',
},
junitReporter: {
outputDir: 'coverage',
outputFile: 'junit.xml',
},
};

config.set(karmaConfig);
};
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
"@semantic-release/git": "^9.0.1",
"@semantic-release/release-notes-generator": "^9.0.3",
"@types/express": "^4.17.13",
"@types/chai": "^4.2.21",
"@types/mocha": "^9.0.0",
"@types/jest": "^27.0.1",
"@types/lodash": "^4.14.171",
"@types/node": "^16.0.1",
"@types/sdp-transform": "^2.4.5",
"@typescript-eslint/eslint-plugin": "^4.28.2",
"@typescript-eslint/parser": "^4.28.2",
"chai": "^4.3.4",
"cspell": "^5.6.6",
"eslint": "^7.29.0",
"eslint-config-airbnb-base": "^14.2.1",
Expand All @@ -44,9 +47,23 @@
"eslint-plugin-prettier": "^3.4.0",
"husky": "^7.0.0",
"jest": "^27.0.6",
"karma": "^6.3.4",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.3",
"karma-firefox-launcher": "^2.1.1",
"karma-junit-reporter": "^2.0.1",
"karma-mocha": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-safari-launcher": "^1.0.0",
"karma-sauce-launcher": "^4.3.6",
"karma-typescript": "^5.5.2",
"karma-typescript-es6-transform": "^5.5.2",
"lint-staged": "^11.1.1",
"mocha": "^9.1.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.3.2",
"puppeteer": "^10.4.0",
"rollup": "^2.53.2",
"rollup-plugin-polyfill-node": "^0.7.0",
"rollup-plugin-terser": "^7.0.2",
Expand Down Expand Up @@ -76,6 +93,7 @@
"test:spelling": "cspell \"{README.md,.github/*.md,src/**/*.ts}\"",
"test:unit": "jest",
"test:coverage": "jest --coverage",
"test:integration": "karma start --integration",
"transpile": "tsc",
"transpile:clean": "rimraf ./dist",
"transpile:validate": "tsc --noemit",
Expand Down
3 changes: 3 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ sonar.sources=src
# exclusions
sonar.exclusions=

# coverage exclusions
sonar.coverage.exclusions=src/mocks/*.*, src/*.spec.ts, src/*.integration-test.ts

# coverage reporting
sonar.javascript.lcov.reportPaths=coverage/lcov.info

Expand Down
38 changes: 38 additions & 0 deletions src/media.integration-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* eslint-disable jest/prefer-expect-assertions */
// eslint-disable-next-line import/no-extraneous-dependencies
import { expect } from 'chai';
import { enumerateDevices, getDisplayMedia, getUserMedia } from './media';

describe('Media integration test', () => {
describe('getUserMedia video', () => {
it('should return a video stream', async () => {
const cameraStream: MediaStream = await getUserMedia({ video: true });
expect(cameraStream.getTracks()[0].kind).equal('video');
});
});

describe('getUserMedia audio', () => {
it('should return an audio stream', async () => {
const audioStream: MediaStream = await getUserMedia({ audio: true });
expect(audioStream.getTracks()[0].kind).equal('audio');
});
});

describe('getDisplayMedia', () => {
it('should return a display stream', async () => {
const btn = document.createElement('button');
btn.addEventListener('click', async () => {
const displayStream: MediaStream = await getDisplayMedia({ video: true });
expect(displayStream.getTracks()[0].kind).equal('video');
});
btn.click();
});
});

describe('enumerateDevices', () => {
it('should return all devices', async () => {
const devices: MediaDeviceInfo[] = await enumerateDevices();
expect(devices.length).greaterThan(0);
});
});
});
Loading

0 comments on commit a1de883

Please sign in to comment.