diff --git a/karma.conf.js b/karma.conf.js index b4f58102714..7158090ba7a 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -26,6 +26,16 @@ const webpackConfig = require('./webpack.config')[1]; const USING_TRAVISCI = Boolean(process.env.TRAVIS); const USING_SL = Boolean(process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY); +// If true, runs new suite of Jasmine foundation unit tests. +// Otherwise, runs old Mocha unit tests. +const USE_JASMINE = Boolean(process.env.USE_JASMINE); + +// Files to include in Jasmine tests. +const FILES_TO_USE = [ + 'packages/*/!(node_modules)/**/!(*.d).ts', + 'packages/*/!(*.d).ts', + 'testing/**/*.ts', +]; const HEADLESS_LAUNCHERS = { /** See https://github.com/travis-ci/travis-ci/issues/8836#issuecomment-348248951 */ @@ -63,79 +73,125 @@ const istanbulInstrumenterLoader = { include: path.resolve('./packages'), }; -module.exports = function(config) { - config.set({ - basePath: '', - // Refer https://github.com/karma-runner/karma-mocha - frameworks: ['mocha'], - files: [ - // Refer https://github.com/babel/karma-babel-preprocessor - 'node_modules/@babel/polyfill/dist/polyfill.js', - 'test/unit/index.js', - ], - preprocessors: { - 'test/unit/index.js': ['webpack', 'sourcemap'], +const mochaConfig = { + basePath: '', + // Refer https://github.com/karma-runner/karma-mocha + frameworks: ['mocha'], + files: [ + // Refer https://github.com/babel/karma-babel-preprocessor + 'node_modules/@babel/polyfill/dist/polyfill.js', + 'test/unit/index.js', + ], + preprocessors: { + 'test/unit/index.js': ['webpack', 'sourcemap'], + }, + reporters: ['progress', 'coverage-istanbul'], + + coverageIstanbulReporter: { + 'dir': 'coverage', + 'reports': ['html', 'lcovonly', 'json'], + 'report-config': { + lcovonly: {subdir: '.'}, + json: {subdir: '.', file: 'coverage.json'}, + }, + // Set 'emitWarning = true' to NOT fail tests if the thresholds are not met + 'emitWarning': false, + 'thresholds': { + statements: 95, + branches: 95, + lines: 95, + functions: 95, + }, + }, + + client: { + mocha: { + reporter: 'html', + ui: 'qunit', + + // Number of milliseconds to wait for an individual `test(...)` function to complete. + // The default is 2000. + timeout: 10000, + }, + }, + + webpackMiddleware: { + noInfo: true, + stats: 'minimal', + }, +}; + +const jasmineConfig = { + basePath: '', + files: FILES_TO_USE, + frameworks: ['jasmine', 'karma-typescript'], + karmaTypescriptConfig: { + coverageOptions: { + threshold: { + global: { + // TODO: Raise threshold to at least 90% after more tests have been migrated. + statements: 80, + branches: 80, + functions: 50, + lines: 80, + excludes: [ + 'testing/**/*.ts', + 'packages/!(mdc-checkbox)/**/*', + 'packages/**/component.ts', // Jasmine tests cover foundation/adapter only. + ], + }, + }, + }, + reports: { + html: 'coverage', + lcovonly: 'coverage', + json: { + directory: 'coverage', + filename: 'coverage.json', + }, }, - reporters: ['progress', 'coverage-istanbul'], + tsconfig: './tsconfig.json', + }, + preprocessors: FILES_TO_USE.reduce((obj, file) => { + obj[file] = 'karma-typescript'; + return obj; + }, {}), + reporters: ['progress', 'karma-typescript'], +}; + +module.exports = function(config) { + config.set(Object.assign(USE_JASMINE ? jasmineConfig : mochaConfig, { + logLevel: config.LOG_INFO, port: 9876, colors: true, - logLevel: config.LOG_INFO, browsers: browsers, browserDisconnectTimeout: 40000, browserNoActivityTimeout: 120000, captureTimeout: 240000, concurrency: USING_SL ? 4 : Infinity, customLaunchers: customLaunchers, + })); - coverageIstanbulReporter: { - 'dir': 'coverage', - 'reports': ['html', 'lcovonly', 'json'], - 'report-config': { - lcovonly: {subdir: '.'}, - json: {subdir: '.', file: 'coverage.json'}, - }, - // 'emitWarning' causes the tests to fail if the thresholds are not met - 'emitWarning': false, - 'thresholds': { - statements: 95, - branches: 95, - lines: 95, - functions: 95, - }, - }, - - client: { - mocha: { - reporter: 'html', - ui: 'qunit', - - // Number of milliseconds to wait for an individual `test(...)` function to complete. - // The default is 2000. - timeout: 10000, - }, - }, - - // Refer https://github.com/webpack-contrib/karma-webpack - webpack: Object.assign({}, webpackConfig, { - plugins: [], // Exclude UglifyJs plugin from test build. - mode: 'development', - module: Object.assign({}, webpackConfig.module, { - // Cover source files when not debugging tests. Otherwise, omit coverage instrumenting to get - // uncluttered source maps. - rules: webpackConfig.module.rules.concat(config.singleRun ? [Object.assign({ - enforce: 'post', - test: /\.ts$/, - }, istanbulInstrumenterLoader), Object.assign({ - test: /\.js$/, - }, istanbulInstrumenterLoader)] : []), + if (!USE_JASMINE) { + // Need to set webpack here rather than in `mochaConfig` to read `config.singleRun`. + config.set({ + // Refer https://github.com/webpack-contrib/karma-webpack + webpack: Object.assign({}, webpackConfig, { + plugins: [], // Exclude UglifyJs plugin from test build. + mode: 'development', + module: Object.assign({}, webpackConfig.module, { + // Cover source files when not debugging tests. Otherwise, omit coverage instrumenting to get + // uncluttered source maps. + rules: webpackConfig.module.rules.concat(config.singleRun ? [Object.assign({ + enforce: 'post', + test: /\.ts$/, + }, istanbulInstrumenterLoader), Object.assign({ + test: /\.js$/, + }, istanbulInstrumenterLoader)] : []), + }), }), - }), - - webpackMiddleware: { - noInfo: true, - stats: 'minimal', - }, - }); + }); + } if (USING_SL) { const sauceLabsConfig = { diff --git a/package-lock.json b/package-lock.json index 5b5b741b6b1..d34b9e3f771 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3346,6 +3346,12 @@ "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", "dev": true }, + "@types/jasmine": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.0.tgz", + "integrity": "sha512-kGCRI9oiCxFS6soGKlyzhMzDydfcPix9PpTkr7h11huxOxhWwP37Tg7DYBaQ18eQTNreZEuLkhpbGSqVNZPnnw==", + "dev": true + }, "@types/kss": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/kss/-/kss-3.0.1.tgz", @@ -3759,6 +3765,13 @@ "repeat-string": "^1.5.2" } }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true + }, "ansi-align": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", @@ -3791,6 +3804,12 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, "any-base": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", @@ -5222,6 +5241,23 @@ "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", "dev": true }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -6274,6 +6310,26 @@ "lodash": "^4.5.0" } }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + } + } + }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -9220,6 +9276,12 @@ "event-emitter": "~0.3.5" } }, + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", + "dev": true + }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -9675,6 +9737,12 @@ } } }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", @@ -11189,21 +11257,21 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": false, "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true @@ -11221,14 +11289,14 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "resolved": false, "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, @@ -11246,35 +11314,35 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "resolved": false, "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "resolved": false, "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, @@ -11291,21 +11359,21 @@ }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "resolved": false, "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "resolved": false, "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "resolved": false, "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -11315,14 +11383,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": false, "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -11354,7 +11422,7 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "resolved": false, "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true @@ -11371,7 +11439,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "resolved": false, "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -11381,7 +11449,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -11392,21 +11460,21 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "resolved": false, "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, @@ -11416,14 +11484,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": false, "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, @@ -11433,7 +11501,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true @@ -11461,7 +11529,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, @@ -11471,7 +11539,7 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "resolved": false, "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true @@ -11509,7 +11577,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -11538,7 +11606,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -11551,21 +11619,21 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "resolved": false, "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, @@ -11575,21 +11643,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "resolved": false, "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -11600,14 +11668,14 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": false, "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "resolved": false, "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true @@ -11627,7 +11695,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -11636,7 +11704,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": false, "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -11669,14 +11737,14 @@ }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": false, "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "resolved": false, "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true @@ -11690,21 +11758,21 @@ }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, @@ -11716,7 +11784,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": false, "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -11726,7 +11794,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, @@ -11736,7 +11804,7 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": false, "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true @@ -11759,7 +11827,7 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": false, "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true @@ -11776,7 +11844,7 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true @@ -12781,7 +12849,7 @@ }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "resolved": false, "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { @@ -14561,6 +14629,15 @@ "validate-npm-package-name": "^3.0.0" } }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "~0.5.3" + } + }, "inquirer": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", @@ -14774,6 +14851,12 @@ "is-decimal": "^1.0.0" } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -14919,6 +15002,12 @@ "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=", "dev": true }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", + "dev": true + }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", @@ -14980,6 +15069,15 @@ "xtend": "^4.0.0" } }, + "is-nan": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.2.1.tgz", + "integrity": "sha1-n69ltvttskt/XAYoR16nH5iEAeI=", + "dev": true, + "requires": { + "define-properties": "^1.1.1" + } + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -15296,6 +15394,99 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + } + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, "istanbul-api": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.0.6.tgz", @@ -15578,6 +15769,38 @@ "is-object": "^1.0.1" } }, + "jasmine": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.5.0.tgz", + "integrity": "sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ==", + "dev": true, + "requires": { + "glob": "^7.1.4", + "jasmine-core": "~3.5.0" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "jasmine-core": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz", + "integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==", + "dev": true + }, "jimp": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.6.1.tgz", @@ -16565,6 +16788,31 @@ "which": "^1.2.1" } }, + "karma-coverage": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-1.1.2.tgz", + "integrity": "sha512-eQawj4Cl3z/CjxslYy9ariU4uDh7cCNFZHNWXWRpl0pNeblY/4wHR7M7boTYXWrn9bY0z2pZmr11eKje/S/hIw==", + "dev": true, + "requires": { + "dateformat": "^1.0.6", + "istanbul": "^0.4.0", + "lodash": "^4.17.0", + "minimatch": "^3.0.0", + "source-map": "^0.5.1" + }, + "dependencies": { + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + } + } + }, "karma-coverage-istanbul-reporter": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.4.tgz", @@ -16581,6 +16829,15 @@ "integrity": "sha1-zlj0fCATqIFW1VpdYTN8CZz1u1E=", "dev": true }, + "karma-jasmine": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz", + "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==", + "dev": true, + "requires": { + "jasmine-core": "^3.3" + } + }, "karma-mocha": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", @@ -16625,49 +16882,345 @@ "integrity": "sha512-owti/aGgkxu3hzb+hJMA9CswlfYpLRmM4kZs5tuhlj4S60YWj4rUPFrZIDONC9n4T+OUfk8pHLQqshBmPXuu0g==", "dev": true }, - "karma-webpack": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.0.tgz", - "integrity": "sha512-Ja1o9LLoqWaJyUNhTKaXjWiEH9y7a9H3mzP8pYB30SBsgoF5KBS/65NeHFd+QPuT9ITrym8xFt8BZeGbcOfujA==", + "karma-typescript": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/karma-typescript/-/karma-typescript-4.1.1.tgz", + "integrity": "sha512-NiGt3Lh8pxKY6hSW4mBV7X45zfB+EA4ezVMNN/vnzLvN+du0UoEc8lTAhrD/DMrjKP3wDlpabku652svRyguXg==", "dev": true, "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^2.0.6" + "acorn": "^6.0.5", + "acorn-walk": "^6.1.1", + "assert": "^2.0.0", + "async": "^3.0.1", + "browser-resolve": "^1.11.3", + "browserify-zlib": "^0.2.0", + "buffer": "^5.2.1", + "combine-source-map": "^0.8.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "convert-source-map": "^1.6.0", + "crypto-browserify": "^3.12.0", + "diff": "^4.0.1", + "domain-browser": "^1.2.0", + "events": "^3.0.0", + "glob": "^7.1.3", + "https-browserify": "^1.0.0", + "istanbul": "0.4.5", + "json-stringify-safe": "^5.0.1", + "karma-coverage": "^1.1.1", + "lodash": "^4.17.11", + "log4js": "^4.0.1", + "minimatch": "^3.0.4", + "os-browserify": "^0.3.0", + "pad": "^3.2.0", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "punycode": "^2.1.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.1.1", + "remap-istanbul": "^0.13.0", + "source-map": "^0.7.3", + "stream-browserify": "^2.0.2", + "stream-http": "^3.0.0", + "string_decoder": "^1.2.0", + "timers-browserify": "^2.0.10", + "tmp": "^0.1.0", + "tty-browserify": "^0.0.1", + "url": "^0.11.0", + "util": "^0.12.0", + "vm-browserify": "1.1.0" }, "dependencies": { - "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + }, + "assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", "dev": true, "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" } - } - } - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + }, + "async": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz", + "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==", + "dev": true + }, + "buffer": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "log4js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "dev": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "path-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.0.tgz", + "integrity": "sha512-Hkavx/nY4/plImrZPHRk2CL9vpOymZLgEbMNX1U0bjcBL7QN9wODxyx0yaMZURSQaUtSEvDrfAvxa9oPb0at9g==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rfdc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "stream-http": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.0.tgz", + "integrity": "sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^3.0.6", + "xtend": "^4.0.0" + } + }, + "streamroller": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "dev": true, + "requires": { + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "util": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.1.tgz", + "integrity": "sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" + } + } + } + }, + "karma-webpack": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.0.tgz", + "integrity": "sha512-Ja1o9LLoqWaJyUNhTKaXjWiEH9y7a9H3mzP8pYB30SBsgoF5KBS/65NeHFd+QPuT9ITrym8xFt8BZeGbcOfujA==", + "dev": true, + "requires": { + "async": "^2.0.0", + "babel-runtime": "^6.0.0", + "loader-utils": "^1.0.0", + "lodash": "^4.0.0", + "source-map": "^0.5.6", + "webpack-dev-middleware": "^2.0.6" + }, + "dependencies": { + "webpack-dev-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", + "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", + "dev": true, + "requires": { + "loud-rejection": "^1.6.0", + "memory-fs": "~0.4.1", + "mime": "^2.1.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "url-join": "^2.0.2", + "webpack-log": "^1.0.1" + } + } + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { @@ -17166,6 +17719,12 @@ "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -19705,6 +20264,18 @@ } } }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-is": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", + "dev": true + }, "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", @@ -19783,6 +20354,100 @@ } } }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "es-abstract": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.2.tgz", + "integrity": "sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -20290,6 +20955,15 @@ } } }, + "pad": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pad/-/pad-3.2.0.tgz", + "integrity": "sha512-2u0TrjcGbOjBTJpyewEl4hBO3OeX5wWue7eIFPzQTg6wFSvoaHcBTTUY5m+n0hd04gmTCPuY0kCpVIVuw5etwg==", + "dev": true, + "requires": { + "wcwidth": "^1.0.1" + } + }, "pako": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", @@ -20644,6 +21318,35 @@ "find-up": "^1.0.0" } }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + } + } + }, "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", @@ -22367,6 +23070,37 @@ } } }, + "remap-istanbul": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.13.0.tgz", + "integrity": "sha512-rS5ZpVAx3fGtKZkiBe1esXg5mKYbgW9iz8kkADFt3p6lo3NsBBUX1q6SwdhwUtYCGnr7nK6gRlbYK3i8R0jbRA==", + "dev": true, + "requires": { + "istanbul": "0.4.5", + "minimatch": "^3.0.4", + "plugin-error": "^1.0.1", + "source-map": "0.6.1", + "through2": "3.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "through2": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", + "integrity": "sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==", + "dev": true, + "requires": { + "readable-stream": "2 || 3", + "xtend": "~4.0.1" + } + } + } + }, "remark": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", @@ -23860,6 +24594,72 @@ "function-bind": "^1.0.2" } }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + }, + "dependencies": { + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -26083,6 +26883,12 @@ "integrity": "sha1-qFjtLjKMWVOZphroig4A+3Vr4Bw=", "dev": true }, + "vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true + }, "void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", diff --git a/package.json b/package.json index c9825b0525f..377271c5468 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,12 @@ "dist": "npm run build && npm run build:min && npm run build:esmodules", "docgen": "npm run clean && npm run build:esmodules && tsc ./scripts/documentation/tsdoc.ts --resolveJsonModule && node ./scripts/documentation/tsdoc.js", "fix:js": "eslint --fix test scripts webpack.config.js karma.conf.js", - "fix:ts": "tslint --exclude \"**/*.d.ts\" --fix \"packages/**/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\"", + "fix:ts": "tslint --exclude \"**/*.d.ts\" --exclude \"packages/**/test/*.ts\" --fix \"packages/test/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\"", "fix:css": "stylelint --fix \"packages/**/*.scss\"; stylelint --fix --config=test/screenshot/.stylelintrc.yaml \"test/screenshot/**/*.scss\"", "fix": "npm-run-all --parallel fix:*", "lint:css": "stylelint \"packages/**/*.scss\" && stylelint --config=test/screenshot/.stylelintrc.yaml \"test/screenshot/**/*.scss\"", "lint:js": "eslint test scripts webpack.config.js karma.conf.js", - "lint:ts": "tslint --exclude \"**/*.d.ts\" \"packages/**/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\"", + "lint:ts": "tslint --exclude \"**/*.d.ts\" --exclude \"packages/**/test/*.ts\" \"packages/test/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\"", "lint:html": "find test/screenshot/spec/ -name '*.html' | grep -v 'index.html$' | xargs htmllint", "lint:mdc": "ts-node --project scripts/tsconfig.json -- scripts/lint-mdc.ts", "lint": "npm-run-all --parallel lint:*", @@ -34,11 +34,14 @@ "screenshot:watch": "node test/screenshot/run.js build --watch", "screenshot:webpack": "webpack --config=test/screenshot/webpack.config.js --progress --display=minimal", "start": "npm-run-all --parallel screenshot:serve screenshot:watch", - "test:watch": "karma start --auto-watch", - "test:unit": "karma start --single-run", "test:dependency": "./scripts/dependency-test.sh", "test:feature-targeting": "node test/scss/verify-feature-targeting.js", "test:site": "npm run clean:site && ./scripts/site-generator-test.sh", + "test:unit": "npm run test:jasmineunit; npm run test:mochaunit", + "test:jasmineunit": "USE_JASMINE=true karma start --single-run", + "test:jasminewatch": "USE_JASMINE=true karma start --auto-watch", + "test:mochaunit": "karma start --single-run", + "test:mochawatch": "karma start --auto-watch", "version": "cat lerna.json | grep -e '^ \"version\": ' | awk '{print $2}' | sed 's/[\",]//g'" }, "devDependencies": { @@ -52,6 +55,7 @@ "@octokit/rest": "^16.15.0", "@types/babel__traverse": "^7.0.6", "@types/glob": "^7.1.1", + "@types/jasmine": "^3.5.0", "@types/node": "^12.0.10", "@types/resolve": "0.0.8", "argparse": "^1.0.10", @@ -93,6 +97,8 @@ "htmllint-cli": "0.0.7", "is-online": "^8.0.0", "istanbul-instrumenter-loader": "^3.0.0", + "jasmine": "^3.5.0", + "jasmine-core": "^3.5.0", "jimp": "^0.6.1", "jsdom": "^13.1.0", "json-stable-stringify": "^1.0.1", @@ -101,10 +107,12 @@ "karma-chrome-launcher": "^2.0.0", "karma-coverage-istanbul-reporter": "^2.0.4", "karma-firefox-launcher": "^1.0.0", + "karma-jasmine": "^2.0.1", "karma-mocha": "^1.3.0", "karma-sauce-launcher": "^1.0.0", "karma-sourcemap-loader": "^0.3.7", "karma-tap": "^4.0.0", + "karma-typescript": "^4.1.1", "karma-webpack": "^3.0.0", "lerna": "^3.6.0", "lolex": "3.1.0", diff --git a/packages/mdc-checkbox/.npmignore b/packages/mdc-checkbox/.npmignore index f0e06b3b5ec..39911f832af 100644 --- a/packages/mdc-checkbox/.npmignore +++ b/packages/mdc-checkbox/.npmignore @@ -1,2 +1,4 @@ *.ts !*.d.ts +*_test.d.ts +test/**/* diff --git a/packages/mdc-checkbox/test/foundation.test.ts b/packages/mdc-checkbox/test/foundation.test.ts new file mode 100644 index 00000000000..f5ef21170af --- /dev/null +++ b/packages/mdc-checkbox/test/foundation.test.ts @@ -0,0 +1,437 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +import 'jasmine'; + +import {verifyDefaultAdapter} from '../../../testing/helpers/foundation'; +import {setupFoundationTest} from '../../../testing/helpers/setup'; +import {cssClasses, numbers, strings} from '../constants'; +import MDCCheckboxFoundation from '../foundation'; + +const DESC_UNDEFINED = { + configurable: true, + enumerable: false, + get: undefined, + set: undefined, +}; + +function setupTest() { + const {foundation, mockAdapter} = setupFoundationTest(MDCCheckboxFoundation); + const nativeControl = document.createElement('input'); + nativeControl.setAttribute('type', 'checkbox'); + return {foundation, mockAdapter, nativeControl}; +} + +interface CheckboxState { + checked: boolean; + indeterminate: boolean; +} + +/** + * Sets up tests which execute change events through the change handler which + * the foundation registers. Returns an object containing the following + * properties: + * - foundation - The MDCCheckboxFoundation instance + * - mockAdapter - The adapter given to the foundation. The adapter is + * pre-configured to capture the changeHandler registered as well as respond + * with different mock objects for native controls based on the state given + * to the change() function. + * - change - A function that's passed an object containing two "checked" and + * "boolean" properties, representing the state of the native control after + * it was changed. E.g. `change({checked: true, indeterminate: false})` + * simulates a change event as the result of a checkbox being checked. + */ +function setupChangeHandlerTest() { + const {foundation, mockAdapter} = setupTest(); + mockAdapter.isAttachedToDOM.and.returnValue(true); + mockAdapter.isIndeterminate.and.returnValue(false); + mockAdapter.isChecked.and.returnValue(false); + + foundation.init(); + + const change = (newState: CheckboxState) => { + mockAdapter.hasNativeControl.and.returnValue(true); + mockAdapter.isChecked.and.returnValue(newState.checked); + mockAdapter.isIndeterminate.and.returnValue(newState.indeterminate); + foundation.handleChange(); + }; + + return {foundation, mockAdapter, change}; +} + +function testChangeHandler( + desc: string, changes: CheckboxState|CheckboxState[], + expectedClass: string) { + changes = Array.isArray(changes) ? changes : [changes] + it(`changeHandler: ${desc}`, () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + + (changes as any).forEach(change); + expect(mockAdapter.addClass).toHaveBeenCalledWith(expectedClass); + }); +} + +describe('MDCCheckboxFoundation', () => { + beforeAll(() => { + jasmine.clock().install(); + }); + + it('exports constants', () => { + expect(cssClasses).toEqual(MDCCheckboxFoundation.cssClasses); + expect(numbers).toEqual(MDCCheckboxFoundation.numbers); + expect(strings).toEqual(MDCCheckboxFoundation.strings); + }); + + it('defaultAdapter returns a complete adapter implementation', () => { + verifyDefaultAdapter(MDCCheckboxFoundation, [ + 'addClass', + 'removeClass', + 'setNativeControlAttr', + 'removeNativeControlAttr', + 'forceLayout', + 'isAttachedToDOM', + 'isIndeterminate', + 'isChecked', + 'hasNativeControl', + 'setNativeControlDisabled', + ]); + }); + + it('#init adds the upgraded class to the root element', () => { + const {foundation, mockAdapter} = setupTest(); + foundation.init(); + expect(mockAdapter.addClass).toHaveBeenCalledWith(cssClasses.UPGRADED); + }); + + it('#init adds aria-checked="mixed" if checkbox is initially indeterminate', + () => { + const {foundation, mockAdapter} = setupTest(); + mockAdapter.isIndeterminate.and.returnValue(true); + + foundation.init(); + expect(mockAdapter.setNativeControlAttr) + .toHaveBeenCalledWith( + 'aria-checked', strings.ARIA_CHECKED_INDETERMINATE_VALUE); + }); + + /* + * Shims Object.getOwnPropertyDescriptor for the checkbox's WebIDL attributes. + * Used to test the behavior of overridding WebIDL properties in different + * browser environments. For example, in Safari WebIDL attributes don't + * return get/set in descriptors. + */ + function withMockCheckboxDescriptorReturning( + descriptor: undefined|typeof DESC_UNDEFINED, runTests: () => void) { + const mockGetOwnPropertyDescriptor = + jasmine.createSpy('mockGetOwnPropertyDescriptor'); + mockGetOwnPropertyDescriptor + .withArgs( + HTMLInputElement.prototype, + jasmine.stringMatching('/checked|indeterminate/')) + .and.returnValue(descriptor); + + const originalDesc = + Object.getOwnPropertyDescriptor(Object, 'getOwnPropertyDescriptor'); + Object.defineProperty( + Object, 'getOwnPropertyDescriptor', { + ...originalDesc, + value: mockGetOwnPropertyDescriptor, + }); + runTests(); + + // After running tests, restore original property. + Object.defineProperty( + Object, 'getOwnPropertyDescriptor', originalDesc as PropertyDescriptor); + } + + it('#init handles case when WebIDL attrs cannot be overridden (Safari)', + () => { + const {foundation, nativeControl} = setupTest(); + withMockCheckboxDescriptorReturning(DESC_UNDEFINED, () => { + expect(() => { + foundation.init(); + nativeControl.checked = !nativeControl.checked; + }).not.toThrow(); + }); + }); + + it('#init handles case when property descriptors are not returned at all (Android Browser)', + () => { + const {foundation} = setupTest(); + withMockCheckboxDescriptorReturning(undefined, () => { + expect(() => foundation.init).not.toThrow(); + }); + }); + + it('#destroy handles case when WebIDL attrs cannot be overridden (Safari)', + () => { + const {foundation} = setupTest(); + withMockCheckboxDescriptorReturning(DESC_UNDEFINED, () => { + expect(() => foundation.init).not.toThrow('init sanity check'); + expect(() => foundation.destroy).not.toThrow(); + }); + }); + + it('#setDisabled updates the value of nativeControl.disabled', () => { + const {foundation, mockAdapter} = setupTest(); + foundation.setDisabled(true); + expect(mockAdapter.setNativeControlDisabled).toHaveBeenCalledWith(true); + expect(mockAdapter.setNativeControlDisabled).toHaveBeenCalledTimes(1); + }); + + it('#setDisabled adds mdc-checkbox--disabled class to the root element when set to true', + () => { + const {foundation, mockAdapter} = setupTest(); + foundation.setDisabled(true); + expect(mockAdapter.addClass).toHaveBeenCalledWith(cssClasses.DISABLED); + }); + + it('#setDisabled removes mdc-checkbox--disabled class from the root element when set to false', + () => { + const {foundation, mockAdapter} = setupTest(); + foundation.setDisabled(false); + expect(mockAdapter.removeClass) + .toHaveBeenCalledWith(cssClasses.DISABLED); + }); + + testChangeHandler( + 'unchecked -> checked animation class', { + checked: true, + indeterminate: false, + }, + cssClasses.ANIM_UNCHECKED_CHECKED); + + testChangeHandler( + 'unchecked -> indeterminate animation class', { + checked: false, + indeterminate: true, + }, + cssClasses.ANIM_UNCHECKED_INDETERMINATE); + + testChangeHandler( + 'checked -> unchecked animation class', + [ + { + checked: true, + indeterminate: false, + }, + { + checked: false, + indeterminate: false, + }, + ], + cssClasses.ANIM_CHECKED_UNCHECKED); + + testChangeHandler( + 'checked -> indeterminate animation class', + [ + { + checked: true, + indeterminate: false, + }, + { + checked: true, + indeterminate: true, + }, + ], + cssClasses.ANIM_CHECKED_INDETERMINATE); + + testChangeHandler( + 'indeterminate -> checked animation class', + [ + { + checked: false, + indeterminate: true, + }, + { + checked: true, + indeterminate: false, + }, + ], + cssClasses.ANIM_INDETERMINATE_CHECKED); + + testChangeHandler( + 'indeterminate -> unchecked animation class', + [ + { + checked: true, + indeterminate: true, + }, + { + checked: false, + indeterminate: false, + }, + ], + cssClasses.ANIM_INDETERMINATE_UNCHECKED); + + testChangeHandler( + 'no transition classes applied when no state change', + [ + { + checked: true, + indeterminate: false, + }, + { + checked: true, + indeterminate: false, + }, + ], + cssClasses.ANIM_UNCHECKED_CHECKED); + + it('changing from unchecked to checked adds selected class', () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + change({ + checked: false, + indeterminate: false, + }); + change({ + checked: true, + indeterminate: false, + }); + expect(mockAdapter.addClass).toHaveBeenCalledWith(cssClasses.SELECTED); + }); + + it('changing from unchecked to indeterminate adds selected class', () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + change({ + checked: false, + indeterminate: false, + }); + change({ + checked: false, + indeterminate: true, + }); + expect(mockAdapter.addClass).toHaveBeenCalledWith(cssClasses.SELECTED); + }); + + it('changing from checked to unchecked removes selected class', () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + change({ + checked: true, + indeterminate: false, + }); + change({ + checked: false, + indeterminate: false, + }); + expect(mockAdapter.removeClass).toHaveBeenCalledWith(cssClasses.SELECTED); + }); + + it('changing from indeterminate to unchecked removes selected class', () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + change({ + checked: false, + indeterminate: true, + }); + change({ + checked: false, + indeterminate: false, + }); + expect(mockAdapter.removeClass).toHaveBeenCalledWith(cssClasses.SELECTED); + }); + + it('animation end handler removes animation class after short delay', () => { + const {ANIM_UNCHECKED_CHECKED} = cssClasses; + const {mockAdapter, foundation} = setupTest(); + + foundation.enableAnimationEndHandler_ = true; + foundation.currentAnimationClass_ = ANIM_UNCHECKED_CHECKED; + expect(mockAdapter.removeClass).not.toHaveBeenCalled(); + + foundation.handleAnimationEnd(); + + jasmine.clock().tick(numbers.ANIM_END_LATCH_MS); + expect(mockAdapter.removeClass).toHaveBeenCalledTimes(1); + expect(foundation.enableAnimationEndHandler_).toBe(false); + }); + + it('animation end is debounced if event is called twice', () => { + const {ANIM_UNCHECKED_CHECKED} = cssClasses; + const {mockAdapter, foundation} = setupChangeHandlerTest(); + foundation.enableAnimationEndHandler_ = true; + foundation.currentAnimationClass_ = ANIM_UNCHECKED_CHECKED; + + foundation.handleAnimationEnd(); + + expect(mockAdapter.removeClass).not.toHaveBeenCalled(); + + foundation.handleAnimationEnd(); + + jasmine.clock().tick(numbers.ANIM_END_LATCH_MS); + expect(mockAdapter.removeClass) + .toHaveBeenCalledWith(ANIM_UNCHECKED_CHECKED); + }); + + it('change handler triggers layout for changes within the same frame to correctly restart anims', + () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + + change({checked: true, indeterminate: false}); + expect(mockAdapter.forceLayout).not.toHaveBeenCalled(); + + change({checked: true, indeterminate: true}); + expect(mockAdapter.forceLayout).toHaveBeenCalled(); + }); + + it('change handler updates aria-checked attribute correctly.', () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + + change({checked: true, indeterminate: true}); + expect(mockAdapter.setNativeControlAttr) + .toHaveBeenCalledWith('aria-checked', 'mixed'); + + change({checked: true, indeterminate: false}); + expect(mockAdapter.removeNativeControlAttr) + .toHaveBeenCalledWith('aria-checked'); + }); + + it('change handler does not add animation classes when isAttachedToDOM() is falsy', + () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + mockAdapter.isAttachedToDOM.and.returnValue(false); + + change({checked: true, indeterminate: false}); + expect(mockAdapter.addClass) + .not.toHaveBeenCalledWith( + jasmine.stringMatching('mdc-checkbox--anim')); + }); + + it('change handler does not add animation classes for bogus changes (init -> unchecked)', + () => { + const {mockAdapter, change} = setupChangeHandlerTest(); + + change({checked: false, indeterminate: false}); + expect(mockAdapter.addClass) + .not.toHaveBeenCalledWith( + jasmine.stringMatching('mdc-checkbox--anim')); + }); + + it('change handler does not do anything if checkbox element is not found', + () => { + const {foundation, mockAdapter} = setupTest(); + mockAdapter.hasNativeControl.and.returnValue(false); + expect(() => foundation.handleChange).not.toThrow(); + expect(mockAdapter.setNativeControlAttr).not.toHaveBeenCalled(); + expect(mockAdapter.removeNativeControlAttr).not.toHaveBeenCalled(); + }); +}); diff --git a/scripts/lint-mdc.ts b/scripts/lint-mdc.ts index 4673b1a439d..4578ee564ae 100644 --- a/scripts/lint-mdc.ts +++ b/scripts/lint-mdc.ts @@ -106,7 +106,7 @@ run(); function run() { const inputFilePaths = glob.sync(path.join(PACKAGES_DIR_ABSOLUTE, '**/*.ts'), { - ignore: ['**/node_modules/**', '**/dist/**', '**/*.d.ts'], + ignore: ['**/node_modules/**', '**/dist/**', '**/*.d.ts', '**/test/*.ts'], nodir: true, }); diff --git a/scripts/travis-env-vars.sh b/scripts/travis-env-vars.sh index e4d02c79cdb..4888011f5d8 100755 --- a/scripts/travis-env-vars.sh +++ b/scripts/travis-env-vars.sh @@ -78,7 +78,7 @@ print_all_changed_files if [[ "$TEST_SUITE" == 'unit' ]]; then # Only run unit tests if JS files changed - check_for_testable_files '^karma\.conf\.js$' '^packages/.+\.(js|ts)$' '^test/unit/.+\.(js|ts)$' + check_for_testable_files '^karma\.conf\.js$' '^packages/.+\.(js|ts)$' '^test/unit/.+\.(js|ts)$' '^testing/.+\.ts' fi if [[ "$TEST_SUITE" == 'build' ]]; then @@ -92,6 +92,9 @@ if [[ "$TEST_SUITE" == 'site-generator' ]]; then fi if [[ "$TEST_SUITE" == 'screenshot' ]]; then - # Only run screenshot tests if package JS/Sass files, screenshot test files, or image files changed. - check_for_testable_files '^packages/.+\.(js|ts|css|scss)$' '^test/screenshot/' '\.(png|jpg|jpeg|gif|svg)$' + # Only run screenshot tests if the following change: + # - package (non-unit test) JS/Sass files + # - screenshot test files + # - image files + check_for_testable_files '^packages/(?!.+/test/).+\.(js|ts|css|scss)$' '^test/screenshot/' '\.(png|jpg|jpeg|gif|svg)$' fi diff --git a/testing/helpers/foundation.ts b/testing/helpers/foundation.ts new file mode 100644 index 00000000000..6e0517623c5 --- /dev/null +++ b/testing/helpers/foundation.ts @@ -0,0 +1,114 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +import {MDCFoundation} from '../../packages/mdc-base/foundation'; +import {FoundationConstructor} from './setup'; + +/** + * Sanity tests to ensure the following: + * - Default adapters contain functions + * - All expected adapter functions are accounted for + * - Invoking any of the default methods does not throw an error. + * Every foundation test suite includes this verification. + */ +export function verifyDefaultAdapter( + FoundationClass: FoundationConstructor, expectedMethodNames: string[]) { + const defaultAdapter = FoundationClass.defaultAdapter as { + [key: string]: any; + }; + const adapterKeys = Object.keys(defaultAdapter); + const actualMethodNames = + adapterKeys.filter((key) => typeof defaultAdapter[key] === 'function'); + + expect(adapterKeys.length) + .toEqual( + actualMethodNames.length, 'Every adapter key must be a function'); + + // Test for equality without requiring that the array be in a specific order. + const actualArray = actualMethodNames.slice().sort(); + const expectedArray = expectedMethodNames.slice().sort(); + expect(expectedArray) + .toEqual(actualArray, getUnequalArrayMessage(actualArray, expectedArray)); + + // Test default methods. + actualMethodNames.forEach((method) => { + expect(() => { + defaultAdapter[method](); + }).not.toThrow(); + }); +} + +function getUnequalArrayMessage( + actualArray: string[], expectedArray: string[]): string { + const format = (values: string[], singularName: string): string => { + const count = values.length; + if (count === 0) { + return ''; + } + const plural = count === 1 ? '' : 's'; + const str = values.join(', '); + return `${count} ${singularName}${plural}: ${str}`; + }; + + const getAddedStr = + (actualSet: Set, expectedSet: Set): string => { + const addedArray: string[] = []; + actualSet.forEach((val) => { + if (!expectedSet.has(val)) { + addedArray.push(val); + } + }); + return format(addedArray, 'unexpected method'); + }; + + const getRemovedStr = + (actualSet: Set, expectedSet: Set): string => { + const removedArray: string[] = []; + expectedSet.forEach((val) => { + if (!actualSet.has(val)) { + removedArray.push(val); + } + }); + return format(removedArray, 'missing method'); + }; + + const toSet = (array: string[]): Set => { + const set: Set = new Set(); + array.forEach((value) => { + set.add(value); + }); + return set; + }; + + const actualSet = toSet(actualArray); + const expectedSet = toSet(expectedArray); + const addedStr = getAddedStr(actualSet, expectedSet); + const removedStr = getRemovedStr(actualSet, expectedSet); + const messages = [addedStr, removedStr].filter((val) => val.length > 0); + + if (messages.length === 0) { + return ''; + } + + return `Found ${messages.join('; ')}`; +} diff --git a/testing/helpers/setup.ts b/testing/helpers/setup.ts new file mode 100644 index 00000000000..6934d4314b7 --- /dev/null +++ b/testing/helpers/setup.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright 2019 Google Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +import {MDCFoundation} from '../../packages/mdc-base/foundation'; + +type MDCFoundationStatics = typeof MDCFoundation; + +// `extends MDCFoundationStatics` to include MDCFoundation statics in type +// definition. +export interface FoundationConstructor extends + MDCFoundationStatics { + new(...args: any[]): F; +} + +export function setupFoundationTest( + FoundationClass: FoundationConstructor) { + const mockAdapter = jasmine.createSpyObj( + FoundationClass.name, FoundationClass.defaultAdapter); + const foundation = new FoundationClass(mockAdapter); + return {foundation, mockAdapter}; +}