diff --git a/docs/browser_support.md b/docs/browser_support.md index 749f924d..7a57efdd 100644 --- a/docs/browser_support.md +++ b/docs/browser_support.md @@ -1,105 +1,15 @@ # Browser support The library supports all popular browsers. -We use the following command to determine which browsers to support: - -```bash -npx browserslist "cover 96% in us, not IE < 11" -``` +We aim to cover at least 99% of all users according to the Fingerprint Pro statistics. At the moment, these browsers are: -- **Internet Explorer** 11 ([see the section below](#old-browsers-requirements)) -- **Edge** 93+ -- **Chrome** 49+ -- **Firefox** 52+ -- **Desktop Safari** 12.1+ -- **Mobile Safari** 10.3+ -- **Samsung Internet** 14.0+ -- **Android Browser** 4.4+ ([see the section below](#old-browsers-requirements)) +- **Edge** 105+ +- **Chrome** 65+ +- **Firefox** 75+ +- **Desktop Safari** 12.1+ +- **Mobile Safari** 12.0+ +- **Samsung Internet** 14.0+ Other browsers will probably also work, but we don't guarantee it. - -## Old browsers requirements - -### `import()` support - -If you use the "Browser ECMAScript module" installation methods, you may have an error. -Old browsers don't support [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import). -Replace it with a ` - -``` - -### Polyfills - -Very old browsers like Internet Explorer 11 and Android Browser 4.4 -require a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) polyfill to work. -Add a Promise polyfill before loading the BotD agent. -Examples for various installation methods: - -#### Webpack/Rollup/NPM/Yarn - -```bash -# Install the polyfill package first: -npm i promise-polyfill -# or -yarn add promise-polyfill -``` - -```diff -+ import 'promise-polyfill/src/polyfill' - import BotD from '@fingerprintjs/botd' - - // ... -``` - -#### UMD - -```diff - require( - [ - 'https://openfpcdn.io/botd/v1/umd.min.js', -+ 'https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js', - ], - function (BotD) { - // ... - } - ) -``` - -#### CommonJS syntax: - -```diff -+ require('promise-polyfill/src/polyfill') - const BotD = require('@fingerprintjs/botd') - - // ... -``` - -### Code syntax - -Old browsers like IE11 don't support `const`, `let` and arrow functions (`=>`). -Use `var` and the classic function syntax instead: - -```diff -- const botdPromise = BotD.load() -+ var botdPromise = BotD.load() - - botdPromise -- .then(fp => fp.detect()) -+ .then(function (fp) { return fp.detect() }) -- .then(result => { -+ .then(function (result) { - // Handle the result - }) -``` diff --git a/karma.conf.ts b/karma.conf.ts index d782da3a..1552f85b 100644 --- a/karma.conf.ts +++ b/karma.conf.ts @@ -1,181 +1,11 @@ -import { Config, CustomLauncher } from 'karma' -import { KarmaTypescriptConfig } from 'karma-typescript/dist/api/configuration' -import { karmaPlugin, setHttpsAndServerForKarma, BrowserFlags } from '@fpjs-incubator/broyster/node' - -declare module 'karma' { - interface ConfigOptions { - karmaTypescriptConfig?: KarmaTypescriptConfig | undefined - } - - interface Config extends ConfigOptions { - preset?: string - reporters: ConfigOptions['reporters'] - } -} - -// 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. Todo: solve it with the support. -/* -const chromeIncognitoCapabilities = { - 'goog:chromeOptions': { - args: ['--incognito'], +import { makeKarmaConfigurator } from '@fpjs-incubator/broyster/node' + +module.exports = makeKarmaConfigurator({ + projectName: 'BotD', + includeFiles: ['src/**/*.ts', 'tests/**/*.ts', 'test-dist/botd.min.js'], + configureCustom(karmaConfig) { + karmaConfig.set({ + failOnEmptyTestSuite: false, + }) }, -} -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_Chrome57: { platform: 'Windows', osVersion: '10', browserName: 'Chrome', browserVersion: '57', useHttps: true }, - // Windows10_Chrome57_Incognito: { platform: 'Windows', osVersion: '10', browserName: 'Chrome', browserVersion: '57', ...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_Firefox67: { platform: 'Windows', osVersion: '10', browserName: 'Firefox', browserVersion: '67', useHttps: true }, - // Windows10_Firefox67_Incognito: { platform: 'Windows', osVersion: '10', browserName: 'Firefox', browserVersion: '67', ...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.14_Safari12': { platform: 'OS X', osVersion: 'Mojave', browserName: 'Safari', browserVersion: '12', useHttps: true }, - OSX12_Safari15: { platform: 'OS X', osVersion: 'Monterey', browserName: 'Safari', browserVersion: '15', useHttps: false }, - OSX13_Safari16: { platform: 'OS X', osVersion: 'Ventura', browserName: 'Safari', browserVersion: '16', useHttps: false }, - OSX13_ChromeLatest: { platform: 'OS X', osVersion: 'Ventura', browserName: 'Chrome', browserVersion: 'latest-beta', useHttps: true }, - // OSX13_ChromeLatest_Incognito: { platform: 'OS X', osVersion: 'Ventura', browserName: 'Chrome', browserVersion: 'latest-beta, ...chromeIncognitoCapabilities }, - OSX13_FirefoxLatest: { platform: 'OS X', osVersion: 'Ventura', browserName: 'Firefox', browserVersion: 'latest-beta', useHttps: true }, - // OSX13_FirefoxLatest_Incognito: { platform: 'OS X', osVersion: 'Ventura', browserName: 'Firefox', browserVersion: 'latest-beta, ...firefoxIncognitoCapabilities }, - OSX13_EdgeLatest: { platform: 'OS X', osVersion: 'Ventura', browserName: 'Edge', browserVersion: 'latest-beta', useHttps: true }, - Android13_ChromeLatest: { deviceName: ['Google Pixel 7', 'Google Pixel 7 Pro', 'Google Pixel 6 Pro'], platform: 'Android', osVersion: '13.0', browserName: 'Chrome', browserVersion: 'latest-beta', useHttps: true, flags: [BrowserFlags.MobileUserAgent], }, - iOS11_Safari: { deviceName: ['iPhone 8 Plus', 'iPhone 6S', 'iPhone 8', 'iPhone 6'], platform: 'iOS', osVersion: '11', browserName: 'Safari', useHttps: true, flags: [BrowserFlags.MobileUserAgent], }, - iOS12_Safari: { deviceName: ['iPhone XS', 'iPhone 6S', 'iPhone 8 Plus', 'iPhone XR'], platform: 'iOS', osVersion: '12', browserName: 'Safari', useHttps: true, flags: [BrowserFlags.MobileUserAgent], }, - iOS13_Safari: { deviceName: ['iPhone 11 Pro', 'iPhone 8', 'iPhone XS', 'iPhone 11 Pro Max'], platform: 'iOS', osVersion: '13', browserName: 'Safari', useHttps: true, flags: [BrowserFlags.MobileUserAgent], }, - iOS14_Safari: { deviceName: ['iPhone 11', 'iPhone XS', 'iPhone 12 Pro', 'iPhone 12 mini'], platform: 'iOS', osVersion: '14', browserName: 'Safari', useHttps: true, flags: [BrowserFlags.MobileUserAgent], }, - iOS15_Safari: { deviceName: ['iPhone 13', 'iPhone 13 Mini', 'iPhone 11 Pro', 'iPhone 11'], platform: 'iOS', osVersion: '15', browserName: 'Safari', useHttps: true, flags: [BrowserFlags.MobileUserAgent], }, - iOS16_Safari: { deviceName: ['iPhone 14', 'iPhone 14 Pro Max', 'iPhone 14 Pro', 'iPhone 14 Plus'], platform: 'iOS', osVersion: '16', browserName: 'Safari', useHttps: true, flags: [BrowserFlags.MobileUserAgent],}, -} - -/* eslint-enable max-len */ - -function makeBuildNumber() { - return `No CI ${Math.floor(Math.random() * 1e10)}` -} - -function setupLocal(config: Config) { - const ciSpecificFiles = ['resources/karma/karma_global_setup_retries.ts'] - const ciEnabled = process.env.CI - const files = [...(ciEnabled ? ciSpecificFiles : []), 'src/**/*.ts', 'tests/**/*.ts', 'test-dist/botd.min.js'] - - config.set({ - frameworks: ['jasmine', 'karma-typescript'], - files, - preprocessors: { - '**/*.ts': 'karma-typescript', - }, - reporters: ['spec', 'summary'], - browsers: ['ChromeHeadless', 'FirefoxHeadless'], - concurrency: 3, - - karmaTypescriptConfig: { - tsconfig: 'tsconfig.json', - compilerOptions: { - module: 'commonjs', - sourceMap: true, - }, - include: files, - }, - - specReporter: { - suppressSummary: true, - suppressErrorSummary: true, - suppressPassed: true, - suppressSkipped: true, - }, - }) -} - -function setupBrowserstack(config: Config) { - setupLocal(config) - - const customLaunchers: Record = {} - for (const [key, data] of Object.entries(browserstackBrowsers)) { - customLaunchers[key] = { - base: 'BrowserStack', - name: key.replace(/_/g, ' '), - ...data, - } - } - - config.set({ - reporters: [...(config.reporters || []), 'BrowserStack'], - plugins: [karmaPlugin, 'karma-*'], - browsers: Object.keys(customLaunchers), - customLaunchers, - concurrency: 5, - failOnEmptyTestSuite: false, - retryLimit: 3, - captureTimeout: 15_000, - browserStack: { - project: 'BotD', - // 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: 20_000, - queueTimeout: 300_000, - }, - }) - setHttpsAndServerForKarma(config) -} - -function setupBrowserStackBetaBuilds(config: Config) { - setupBrowserstack(config) - - const customLaunchers: Record = {} - for (const [key, data] of Object.entries(browserstackBrowsers)) { - if ('browserVersion' in data && data['browserVersion'].includes('beta')) { - customLaunchers[key] = { - base: 'BrowserStack', - name: key.replace(/_/g, ' '), - ...data, - } - } - } - - config.set({ - browsers: Object.keys(customLaunchers), - customLaunchers, - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - browserStack: { ...config.browserStack!, project: 'Monitoring' }, - }) -} - -/** - * Add `--preset local` or `--preset browserstack` to the Karma command to choose where to run the tests. - */ -module.exports = (config: Config) => { - switch (config.preset) { - case 'local': - return setupLocal(config) - case 'browserstack': - return setupBrowserstack(config) - case 'browserstack-beta': - return setupBrowserStackBetaBuilds(config) - default: - throw new Error('No --preset option is set or an unknown value is set') - } -} +}) diff --git a/package.json b/package.json index f32e795d..7702c8c5 100644 --- a/package.json +++ b/package.json @@ -47,14 +47,11 @@ "check:ssr": "node --require ./dist/botd.cjs.js --eval '' || (echo \"The distributive files can't be used with server side rendering. Make sure the code doesn't use browser API until an exported function is called.\" && exit 1)" }, "devDependencies": { - "@fpjs-incubator/broyster": "^0.1.5", + "@fpjs-incubator/broyster": "^0.1.7", "@rollup/plugin-json": "^5.0.1", "@rollup/plugin-node-resolve": "^15.0.1", "@rollup/plugin-typescript": "^10.0.1", "@types/jasmine": "^3.5.14", - "@types/karma": "^6.3.3", - "@types/karma-spec-reporter": "^0.0.3", - "@types/karma-summary-reporter": "^3.1.0", "@types/ua-parser-js": "^0.7.36", "@types/webpack": "^5.28.0", "@typescript-eslint/eslint-plugin": "^5.40.1", @@ -67,12 +64,6 @@ "eslint-plugin-prettier": "^3.3.1", "html-webpack-plugin": "^5.5.0", "karma": "^6.4.1", - "karma-chrome-launcher": "^3.1.1", - "karma-firefox-launcher": "^2.1.2", - "karma-jasmine": "^4.0.2", - "karma-spec-reporter": "^0.0.34", - "karma-summary-reporter": "^3.1.1", - "karma-typescript": "^5.5.3", "license-webpack-plugin": "^4.0.2", "prettier": "^2.2.1", "promise-polyfill": "^8.2.0", diff --git a/playground/index.ts b/playground/index.ts index 51d91aa5..4a12bdaa 100644 --- a/playground/index.ts +++ b/playground/index.ts @@ -6,7 +6,9 @@ import { getMozAppearanceSupport, isAndroid, isDesktopWebKit, + isIPad, } from '../src/utils/browser' +import { getBrowserVersion } from '../tests/utils' import './style.css' type DetectionResult = @@ -40,10 +42,12 @@ const runDetection = async (): Promise => { const debugData = { browserEngineKind: getBrowserEngineKind(), browserKind: getBrowserKind(), + browserVersion: getBrowserVersion(), documentFocus: getDocumentFocus(), mozAppearanceSupport: getMozAppearanceSupport(), isAndroid: isAndroid(), isDesktopWebKit: isDesktopWebKit(), + isIPad: isIPad(), } return { diff --git a/playground/webpack.config.ts b/playground/webpack.config.ts index 6966df46..3ea5be70 100644 --- a/playground/webpack.config.ts +++ b/playground/webpack.config.ts @@ -57,6 +57,8 @@ const config: Configuration = { performance: { hints: isDev ? false : 'error', + maxAssetSize: Infinity, + maxEntrypointSize: Infinity, }, } diff --git a/resources/karma/karma_global_setup_retries.ts b/resources/karma/karma_global_setup_retries.ts deleted file mode 100644 index b6dbe2a0..00000000 --- a/resources/karma/karma_global_setup_retries.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { retryFailedTests } from '@fpjs-incubator/broyster/browser' - -retryFailedTests(3, 100) diff --git a/src/sources/notification_permissions.test.ts b/src/sources/notification_permissions.test.ts index 5e558081..ffe256ed 100644 --- a/src/sources/notification_permissions.test.ts +++ b/src/sources/notification_permissions.test.ts @@ -1,20 +1,29 @@ -import { getBrowserMajorVersion, getBrowserVersion, isHeadlessChrome, isMobile, isWebKit } from '../../tests/utils' -import { BotdError } from '../types' +import { getBrowserVersion, isHeadlessChrome, isMobile, isWebKit } from '../../tests/utils' +import { BotdError, BrowserEngineKind, BrowserKind } from '../types' +import { getBrowserEngineKind, getBrowserKind } from '../utils/browser' import getNotificationPermissions from './notification_permissions' describe('Sources', () => { describe('notificaionPermissions', () => { it('returns an expected value or throws', async () => { const { major, minor } = getBrowserVersion() ?? { major: 0, minor: 0 } - if (isWebKit() && (major < 16 || (major === 16 && minor < 5))) { - await expectAsync(getNotificationPermissions()).toBeRejectedWithError( - BotdError, - isMobile() - ? 'window.Notification is undefined' - : (getBrowserMajorVersion() ?? 0) < 16 - ? 'navigator.permissions is undefined' - : 'notificationPermissions signal unexpected behaviour', - ) + + if ( + getBrowserKind() === BrowserKind.Safari && + getBrowserEngineKind() === BrowserEngineKind.Webkit && + (isMobile() || major < 16 || (major === 16 && minor < 5)) + ) { + let expected = '' + + if (isMobile()) { + expected = 'window.Notification is undefined' + } else if (major < 16) { + expected = 'navigator.permissions is undefined' + } else { + expected = 'notificationPermissions signal unexpected behaviour' + } + + await expectAsync(getNotificationPermissions()).toBeRejectedWithError(BotdError, expected) return } diff --git a/yarn.lock b/yarn.lock index 8191bcbd..7d0c7184 100644 --- a/yarn.lock +++ b/yarn.lock @@ -314,14 +314,21 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@fpjs-incubator/broyster@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@fpjs-incubator/broyster/-/broyster-0.1.5.tgz#2c9744caf70b59c75195de2a3f84986d5e0fed39" - integrity sha512-Li049XorxkNtF7k2QohFsPSCvNZs7GWG0ukehNJDg5zu/IPZvIHxs7zCp7S4Z4NC7NUzcOVsoMz5+UktRqYujw== +"@fpjs-incubator/broyster@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@fpjs-incubator/broyster/-/broyster-0.1.7.tgz#42a3d83aaf38d033fd3bf5d473ccd6503e4d869b" + integrity sha512-ZqfYa20hVjlVLDFyHdxicH9AAROVLTiqpZG00VSX1GaiCYTimd9mYQ7/k5vv+5ISry3HeZri+S+8BVGIsJ3TGA== dependencies: + "@types/karma" "^6.3.3" async-lock "^1.4.0" - browserstack "~1.5.1" - browserstack-local "^1.5.1" + browserstack "~1.6.1" + browserstack-local "^1.5.5" + karma-chrome-launcher "^3.1.1" + karma-firefox-launcher "^2.1.2" + karma-jasmine "^4.0.2" + karma-spec-reporter "^0.0.35" + karma-summary-reporter "^3.1.1" + karma-typescript "^5.5.3" selenium-webdriver "^4.7.0" tslib "^2.4.1" @@ -598,21 +605,7 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== -"@types/karma-spec-reporter@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/karma-spec-reporter/-/karma-spec-reporter-0.0.3.tgz#f70bad339e2f84ad3dac995f41f67c74a68308cf" - integrity sha512-ol9pUJxw5hHyNOGaAhJULMNXEhUyJUh5G7sLTMvWzMmEgRsqX+nOMfwGluftJd++6Vu6f4SS7LPuMF6TKlQ5Dw== - dependencies: - "@types/karma" "*" - -"@types/karma-summary-reporter@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/karma-summary-reporter/-/karma-summary-reporter-3.1.0.tgz#78770cdb689506eb649042c951a13ad5327c2bcf" - integrity sha512-pO+qcPpYx/MakkH9XzOMPNKrlv5LFU6o4vgVHGFNAMf1ptQ+FXvbQ4FUQ36RmtztBqIXG5Asglgzwf2bAFZUEw== - dependencies: - "@types/karma" "*" - -"@types/karma@*", "@types/karma@^6.3.3": +"@types/karma@^6.3.3": version "6.3.3" resolved "https://registry.yarnpkg.com/@types/karma/-/karma-6.3.3.tgz#fc48cc53d13ec9beeea3a2a47a2036ed7647ba29" integrity sha512-nRMec4mTCt+tkpRqh5/pAxmnjzEgAaalIq7mdfLFH88gSRC8+bxejLiSjHMMT/vHIhJHqg4GPIGCnCFbwvDRww== @@ -1317,10 +1310,10 @@ browserslist@^4.14.5, browserslist@^4.21.3: node-releases "^2.0.6" update-browserslist-db "^1.0.9" -browserstack-local@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/browserstack-local/-/browserstack-local-1.5.1.tgz#0d424474cc2b74a9d9a22d00a2282941ff636f34" - integrity sha512-T/wxyWDzvBHbDvl7fZKpFU7mYze6nrUkBhNy+d+8bXBqgQX10HTYvajIGO0wb49oGSLCPM0CMZTV/s7e6LF0sA== +browserstack-local@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/browserstack-local/-/browserstack-local-1.5.5.tgz#f36b625f3b8bfd053f673d85fd1082f2d0759693" + integrity sha512-jKne7yosrMcptj3hqxp36TP9k0ZW2sCqhyurX24rUL4G3eT7OLgv+CSQN8iq5dtkv5IK+g+v8fWvsiC/S9KxMg== dependencies: agent-base "^6.0.2" https-proxy-agent "^5.0.1" @@ -1328,10 +1321,10 @@ browserstack-local@^1.5.1: ps-tree "=1.2.0" temp-fs "^0.9.9" -browserstack@~1.5.1: - version "1.5.3" - resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.5.3.tgz#93ab48799a12ef99dbd074dd595410ddb196a7ac" - integrity sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg== +browserstack@~1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3" + integrity sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw== dependencies: https-proxy-agent "^2.2.1" @@ -1511,7 +1504,7 @@ colorette@^2.0.10, colorette@^2.0.14: resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -colors@1.4.0: +colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -3374,12 +3367,12 @@ karma-jasmine@^4.0.2: dependencies: jasmine-core "^3.6.0" -karma-spec-reporter@^0.0.34: - version "0.0.34" - resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.34.tgz#7dc79cdc76b0e37f17006921439600ae3c648669" - integrity sha512-l5H/Nh9q4g2Ysx2CDU2m+NIPyLQpCVbk9c4V02BTZHw3NM6RO1dq3eRpKXCSSdPt4RGfhHk8jDt3XYkGp+5PWg== +karma-spec-reporter@^0.0.35: + version "0.0.35" + resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.35.tgz#845d9f8b047a452f36fca493d63a72bcc3c865c7" + integrity sha512-ejUIU6yzD2bgcn573ypcRfF1IDnLwkxnSMqXsmmvF/PiOwmQgaLRr8H8blBZmrgxH8qhp+W90Q94h16kEQDWzw== dependencies: - colors "1.4.0" + colors "^1.4.0" karma-summary-reporter@^3.1.1: version "3.1.1"