UNPKG

@fpjs-incubator/broyster

Version:
195 lines (194 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeKarmaConfigurator = void 0; const tslib_1 = require("tslib"); const path = require("path"); const fs_1 = require("fs"); const arguments_1 = require("./arguments"); const karma_plugin_1 = require("./karma_plugin"); const karma_https_config_1 = require("./karma_https_config"); /** * Makes a function that applies an opinionated configuration, used by Fingerprint's projects, to Karma. * * When a Karma configuration file is created, add `--preset local`, `--preset browserstack` or * `--preset browserstack-beta` to the Karma command to choose where to run the tests. * * @example karma.conf.ts in the project's root directory * module.exports = makeKarmaConfigurator({ ... }) * * @example Run tests in the local browsers * karma start --preset local --single-run */ function makeKarmaConfigurator(options) { return (karmaConfig) => tslib_1.__awaiter(this, void 0, void 0, function* () { var _a; switch (karmaConfig.preset) { case 'local': yield setupLocal(karmaConfig, options); break; case 'browserstack': yield setupBrowserstack(karmaConfig, options); break; case 'browserstack-beta': yield setupBrowserstack(karmaConfig, options, true); break; default: throw new Error('No --preset option is set or an unknown value is set'); } yield ((_a = options.configureCustom) === null || _a === void 0 ? void 0 : _a.call(options, karmaConfig)); }); } exports.makeKarmaConfigurator = makeKarmaConfigurator; function setupLocal(karmaConfig, { alwaysRetryTests = false, includeFiles = [], tsconfigPath = 'tsconfig.json' }) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const createdFiles = yield createFilesToInject(); const files = []; if (process.env.CI || alwaysRetryTests) { files.push(createdFiles.setupJasmineRetries); } files.push(...includeFiles); karmaConfig.set({ frameworks: ['jasmine', 'karma-typescript'], files, preprocessors: { '**/*.ts': 'karma-typescript', }, reporters: ['spec', 'summary'], browsers: ['ChromeHeadless', 'FirefoxHeadless'], concurrency: 3, karmaTypescriptConfig: { tsconfig: tsconfigPath, compilerOptions: { module: 'commonjs', sourceMap: true, }, // The `include` and `exclude` options of tsconfig.json are not inherited, because every given `includeFiles` file // must be compiled, and it makes no sense to compile anything else. include: { mode: 'replace', values: files.filter((file) => typeof file === 'string' && /(\*|\.ts)$/.test(file)), }, exclude: { mode: 'replace', values: [] }, }, specReporter: { suppressSummary: true, suppressErrorSummary: true, suppressPassed: true, suppressSkipped: true, }, }); }); } function setupBrowserstack(karmaConfig, options, onlyBetaBrowsers = false) { return tslib_1.__awaiter(this, void 0, void 0, function* () { yield setupLocal(karmaConfig, options); const customLaunchers = {}; for (const [key, data] of Object.entries(browserstackBrowsers)) { if (onlyBetaBrowsers && !('browserVersion' in data && /beta/i.test(data.browserVersion))) { continue; } customLaunchers[key] = Object.assign({ base: 'BrowserStack', name: key.replace(/_/g, ' ') }, data); } karmaConfig.set({ reporters: [...(karmaConfig.reporters || []), 'BrowserStack'], plugins: [...(karmaConfig.plugins || []), karma_plugin_1.default], browsers: Object.keys(customLaunchers), customLaunchers, concurrency: 5, retryLimit: 3, captureTimeout: 15000, browserDisconnectTolerance: 2, browserDisconnectTimeout: 15000, browserStack: { project: options.projectName, // A build number is required to group testing sessions in the BrowserStack UI. // GitHub Actions will add a value for GITHUB_RUN_ID. More on the environment variables: // https://docs.github.com/en/free-pro-team@latest/actions/reference/environment-variables#default-environment-variables build: process.env.GITHUB_RUN_ID || makeBuildNumber(), // The timeout is reduced for testing sessions to not hold the BrowserStack queue long in case of problems. idleTimeout: 20000, queueTimeout: 300000, }, }); (0, karma_https_config_1.setHttpsAndServerForKarma)(karmaConfig); }); } function createFilesToInject() { return tslib_1.__awaiter(this, void 0, void 0, function* () { // `package.json` is imported using `require` to prevent TypeScript from putting it into `dist` // eslint-disable-next-line @typescript-eslint/no-var-requires const { name: packageName } = require('../package.json'); // The injected files must be within the current working directory, otherwise karma-typescript won't compile them const temporaryDirectory = path.join('node_modules', '.tmp', packageName); yield fs_1.promises.mkdir(temporaryDirectory, { recursive: true }); const filesToCreate = { setupJasmineRetries: { name: 'setup_jasmine_retries.ts', content: `import { retryFailedTests } from '${packageName}/browser'; retryFailedTests(3, 100)`, }, }; const createdFiles = {}; yield Promise.all(Object.keys(filesToCreate).map((id) => tslib_1.__awaiter(this, void 0, void 0, function* () { createdFiles[id] = path.join(temporaryDirectory, filesToCreate[id].name); yield fs_1.promises.writeFile(createdFiles[id], filesToCreate[id].content); }))); return createdFiles; }); } // The shapes of these objects are taken from: // https://github.com/SeleniumHQ/selenium/tree/d8ddb4d83972df0f565ef65264bcb733e7a94584/javascript/node/selenium-webdriver // It doesn't work, trying to work it out with BrowserStack support. /* const chromeIncognitoCapabilities = { 'goog:chromeOptions': { args: ['--incognito'], }, } const firefoxIncognitoCapabilities = { 'moz:firefoxOptions': { prefs: { 'browser.privatebrowsing.autostart': true, }, }, } */ /* * You can find values for any supported browsers in the interactive form at * https://www.browserstack.com/docs/automate/javascript-testing/configure-test-run-options * The keys are arbitrary values. * * Only Chrome is supported on Android, only Safari is supported on iOS: https://www.browserstack.com/question/659 */ /* eslint-disable max-len */ // prettier-ignore const browserstackBrowsers = { Windows10_Chrome73: { platform: 'Windows', osVersion: '10', browserName: 'Chrome', browserVersion: '73', useHttps: true }, // Windows10_Chrome73_Incognito: { platform: 'Windows', osVersion: '10', browserName: 'Chrome', browserVersion: '73', ...chromeIncognitoCapabilities }, Windows11_ChromeLatest: { platform: 'Windows', osVersion: '11', browserName: 'Chrome', browserVersion: 'latest-beta', useHttps: true }, // Windows11_ChromeLatest_Incognito: { platform: 'Windows', osVersion: '11', browserName: 'Chrome', browserVersion: 'latest-beta, ...chromeIncognitoCapabilities }, Windows10_Firefox89: { platform: 'Windows', osVersion: '10', browserName: 'Firefox', browserVersion: '89', useHttps: true, firefoxCapabilities: [['security.csp.enable', true]] }, // Windows10_Firefox89_Incognito: { platform: 'Windows', osVersion: '10', browserName: 'Firefox', browserVersion: '89', ...firefoxIncognitoCapabilities }, Windows11_FirefoxLatest: { platform: 'Windows', osVersion: '11', browserName: 'Firefox', browserVersion: 'latest-beta', useHttps: true }, // Windows11_FirefoxLatest_Incognito: { platform: 'Windows', osVersion: '11', browserName: 'Firefox', browserVersion: 'latest-beta, ...firefoxIncognitoCapabilities }, Windows11_EdgeLatest: { platform: 'Windows', osVersion: '11', browserName: 'Edge', browserVersion: 'latest-beta', useHttps: true }, 'OSX10.15_Safari13': { platform: 'OS X', osVersion: 'Catalina', browserName: 'Safari', browserVersion: '13', useHttps: true }, OSX12_Safari15: { platform: 'OS X', osVersion: 'Monterey', browserName: 'Safari', browserVersion: '15', useHttps: false }, OSX15_Safari18: { platform: 'OS X', osVersion: 'Sequoia', browserName: 'Safari', browserVersion: '18', useHttps: false }, OSX15_ChromeLatest: { platform: 'OS X', osVersion: 'Sequoia', browserName: 'Chrome', browserVersion: 'latest-beta', useHttps: true }, // OSX15_ChromeLatest_Incognito: { platform: 'OS X', osVersion: 'Sequoia', browserName: 'Chrome', browserVersion: 'latest-beta, ...chromeIncognitoCapabilities }, OSX15_FirefoxLatest: { platform: 'OS X', osVersion: 'Sequoia', browserName: 'Firefox', browserVersion: 'latest-beta', useHttps: true }, // OSX15_FirefoxLatest_Incognito: { platform: 'OS X', osVersion: 'Sequoia', browserName: 'Firefox', browserVersion: 'latest-beta, ...firefoxIncognitoCapabilities }, OSX15_EdgeLatest: { platform: 'OS X', osVersion: 'Sequoia', browserName: 'Edge', browserVersion: 'latest-beta', useHttps: true }, Android14_ChromeLatest: { platform: 'Android', osVersion: '14.0', browserName: 'Chrome', browserVersion: 'latest-beta', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, Android14_SamsungLatest: { platform: 'Android', osVersion: '14.0', browserName: 'Samsung', browserVersion: 'latest-beta', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, iOS13_Safari: { platform: 'iOS', osVersion: '13', browserName: 'Safari', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, iOS14_Safari: { platform: 'iOS', osVersion: '14', browserName: 'Safari', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, iOS15_Safari: { platform: 'iOS', osVersion: '15', browserName: 'Safari', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, iOS16_Safari: { platform: 'iOS', osVersion: '16', browserName: 'Safari', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, iOS17_Safari: { platform: 'iOS', osVersion: '17', browserName: 'Safari', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, iOS18_Safari: { platform: 'iOS', osVersion: '18', browserName: 'Safari', useHttps: true, flags: [arguments_1.Arguments.MobileUserAgent] }, }; /* eslint-enable max-len */ function makeBuildNumber() { return `No CI ${Math.floor(Math.random() * 1e10)}`; }